Import rust-debcargo_2.8.1.orig.tar.gz
authorFabian Grünbichler <debian@fabian.gruenbichler.email>
Wed, 18 Feb 2026 11:25:38 +0000 (12:25 +0100)
committerFabian Grünbichler <debian@fabian.gruenbichler.email>
Wed, 18 Feb 2026 11:25:38 +0000 (12:25 +0100)
[dgit import orig rust-debcargo_2.8.1.orig.tar.gz]

292 files changed:
.cargo_vcs_info.json [new file with mode: 0644]
.gitignore [new file with mode: 0644]
.gitlab-ci.yml [new file with mode: 0644]
Cargo.lock [new file with mode: 0644]
Cargo.toml [new file with mode: 0644]
Cargo.toml.orig [new file with mode: 0644]
HACKING.md [new file with mode: 0644]
README.md [new file with mode: 0644]
TODO.md [new file with mode: 0644]
debcargo.toml.example [new file with mode: 0644]
manpages/debcargo-build-order.1 [new file with mode: 0644]
manpages/debcargo-deb-dependencies.1 [new file with mode: 0644]
manpages/debcargo-deb-src-name.1 [new file with mode: 0644]
manpages/debcargo-extract.1 [new file with mode: 0644]
manpages/debcargo-package.1 [new file with mode: 0644]
manpages/debcargo-update-dependencies.1 [new file with mode: 0644]
manpages/debcargo-update.1 [new file with mode: 0644]
manpages/debcargo.1 [new file with mode: 0644]
src/bin/debcargo.rs [new file with mode: 0644]
src/build_order.rs [new file with mode: 0644]
src/cli.rs [new file with mode: 0644]
src/config.rs [new file with mode: 0644]
src/crates.rs [new file with mode: 0644]
src/deb_dependencies.rs [new file with mode: 0644]
src/debian/changelog.rs [new file with mode: 0644]
src/debian/changelog/tests.rs [new file with mode: 0644]
src/debian/control.rs [new file with mode: 0644]
src/debian/control/tests.rs [new file with mode: 0644]
src/debian/copyright.rs [new file with mode: 0644]
src/debian/copyright/tests.rs [new file with mode: 0644]
src/debian/dependency.rs [new file with mode: 0644]
src/debian/dependency/tests.rs [new file with mode: 0644]
src/debian/licenses/AGPL-3.0 [new file with mode: 0644]
src/debian/licenses/Apache-2.0 [new file with mode: 0644]
src/debian/licenses/BSD-2-Clause [new file with mode: 0644]
src/debian/licenses/BSD-3-Clause [new file with mode: 0644]
src/debian/licenses/CC0-1.0 [new file with mode: 0644]
src/debian/licenses/GPL-2.0 [new file with mode: 0644]
src/debian/licenses/GPL-3.0 [new file with mode: 0644]
src/debian/licenses/ISC [new file with mode: 0644]
src/debian/licenses/LGPL-2.0 [new file with mode: 0644]
src/debian/licenses/LGPL-2.1 [new file with mode: 0644]
src/debian/licenses/LGPL-3.0 [new file with mode: 0644]
src/debian/licenses/MIT [new file with mode: 0644]
src/debian/licenses/MITNFA [new file with mode: 0644]
src/debian/licenses/MPL-1.1 [new file with mode: 0644]
src/debian/licenses/MPL-2.0 [new file with mode: 0644]
src/debian/licenses/Unlicense [new file with mode: 0644]
src/debian/licenses/Zlib [new file with mode: 0644]
src/debian/mod.rs [new file with mode: 0644]
src/errors.rs [new file with mode: 0644]
src/lib.rs [new file with mode: 0644]
src/package.rs [new file with mode: 0644]
src/update_dependencies.rs [new file with mode: 0644]
src/util.rs [new file with mode: 0644]
tests/clap_override.toml [new file with mode: 0644]
tests/config_tests.rs [new file with mode: 0644]
tests/configs/aesni-0.10/debian/debcargo.toml [new file with mode: 0644]
tests/configs/aesni-0.10/debian/rules [new file with mode: 0644]
tests/configs/aesni/debian/debcargo.toml [new file with mode: 0644]
tests/configs/aesni/debian/rules [new file with mode: 0644]
tests/configs/afl-0.10/debian/debcargo.toml [new file with mode: 0644]
tests/configs/afl-0.10/debian/rules [new file with mode: 0644]
tests/configs/afl-0.13/debian/debcargo.toml [new file with mode: 0644]
tests/configs/afl-0.13/debian/rules [new file with mode: 0644]
tests/configs/aom-sys-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/ascii-0.8/debian/debcargo.toml [new file with mode: 0644]
tests/configs/ascii-0.8/debian/patches/fix-old-dep.patch [new file with mode: 0644]
tests/configs/ascii-0.8/debian/patches/series [new file with mode: 0644]
tests/configs/aws-lc-fips-sys-0.12/debian/debcargo.toml [new file with mode: 0644]
tests/configs/aws-lc-fips-sys-0.12/debian/rules [new file with mode: 0644]
tests/configs/blas-src-0.6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/blas-src-0.6/debian/patches/drop-accelerate.diff [new file with mode: 0644]
tests/configs/blas-src-0.6/debian/patches/series [new file with mode: 0644]
tests/configs/broken-dh-strip/debian/debcargo.toml [new file with mode: 0644]
tests/configs/broken-dh-strip/debian/rules [new file with mode: 0755]
tests/configs/broken-lto/debian/debcargo.toml [new file with mode: 0644]
tests/configs/broken-lto/debian/rules [new file with mode: 0644]
tests/configs/broken-upstream/debian/debcargo.toml [new file with mode: 0644]
tests/configs/broken-upstream/debian/rules [new file with mode: 0644]
tests/configs/brotli-decompressor-2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/brotli-decompressor-2/debian/rules [new file with mode: 0644]
tests/configs/clang-sys-0.23/debian/debcargo.toml [new file with mode: 0644]
tests/configs/clang-sys-0.26/debian/debcargo.toml [new file with mode: 0644]
tests/configs/clang-sys-1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/clang-sys/debian/debcargo.toml [new file with mode: 0644]
tests/configs/clippy-0.0/debian/debcargo.toml [new file with mode: 0644]
tests/configs/clippy-0.0/debian/rules [new file with mode: 0644]
tests/configs/cmake-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/compiler-builtins-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/compiler-builtins-0.1/debian/rules [new file with mode: 0644]
tests/configs/compiler-error-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/compiler-error-0.1/debian/rules [new file with mode: 0644]
tests/configs/compiletest-rs-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/compiletest-rs-0.3/debian/rules [new file with mode: 0644]
tests/configs/core-arch-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/core-arch-0.1/debian/rules [new file with mode: 0644]
tests/configs/core-error-0.0/debian/debcargo.toml [new file with mode: 0644]
tests/configs/core-error-0.0/debian/rules [new file with mode: 0644]
tests/configs/core-extensions-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/core-extensions-0.1/debian/rules [new file with mode: 0644]
tests/configs/core-foundation-0.9/debian/debcargo.toml [new file with mode: 0644]
tests/configs/core-foundation-0.9/debian/rules [new file with mode: 0644]
tests/configs/core-graphics-0.23/debian/debcargo.toml [new file with mode: 0644]
tests/configs/core-graphics-0.23/debian/rules [new file with mode: 0644]
tests/configs/core-graphics-types-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/core-graphics-types-0.1/debian/rules [new file with mode: 0644]
tests/configs/core-text-20/debian/debcargo.toml [new file with mode: 0644]
tests/configs/core-text-20/debian/rules [new file with mode: 0644]
tests/configs/cpp-demangle-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/dav1d-sys-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/dav1d-sys-0.3/debian/patches/relax-bindgen.patch [new file with mode: 0644]
tests/configs/dav1d-sys-0.3/debian/patches/series [new file with mode: 0644]
tests/configs/dav1d-sys-0.8/debian/debcargo.toml [new file with mode: 0644]
tests/configs/derive-builder-0.9/debian/debcargo.toml [new file with mode: 0644]
tests/configs/derive-builder-0.9/debian/rules [new file with mode: 0644]
tests/configs/diesel-1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/diesel-1/debian/patches/fix-old-dep.patch [new file with mode: 0644]
tests/configs/diesel-1/debian/patches/series [new file with mode: 0644]
tests/configs/diesel-derives-2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/diesel-derives-2/debian/rules [new file with mode: 0644]
tests/configs/dwrote-0.11/debian/debcargo.toml [new file with mode: 0644]
tests/configs/dwrote-0.11/debian/rules [new file with mode: 0644]
tests/configs/exa-0.10/debian/debcargo.toml [new file with mode: 0644]
tests/configs/exa-0.10/debian/rules [new file with mode: 0644]
tests/configs/exa/debian/debcargo.toml [new file with mode: 0644]
tests/configs/exa/debian/rules [new file with mode: 0644]
tests/configs/fd-find-8/debian/debcargo.toml [new file with mode: 0644]
tests/configs/fd-find-8/debian/rules [new file with mode: 0644]
tests/configs/fsevent-0.4/debian/debcargo.toml [new file with mode: 0644]
tests/configs/fsevent-0.4/debian/rules [new file with mode: 0644]
tests/configs/fsevent-sys-2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/fsevent-sys-2/debian/rules [new file with mode: 0644]
tests/configs/heapsize-plugin-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/heapsize-plugin-0.1/debian/rules [new file with mode: 0644]
tests/configs/http-types-2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/http-types-2/debian/patches/fix-features.patch [new file with mode: 0644]
tests/configs/http-types-2/debian/patches/series [new file with mode: 0644]
tests/configs/hyperx-1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/hyperx-1/debian/patches/relax-percent-encoding.patch [new file with mode: 0644]
tests/configs/hyperx-1/debian/patches/series [new file with mode: 0644]
tests/configs/hyperx/debian/debcargo.toml [new file with mode: 0644]
tests/configs/hyperx/debian/patches/relax-percent-encoding.patch [new file with mode: 0644]
tests/configs/hyperx/debian/patches/series [new file with mode: 0644]
tests/configs/iana-time-zone-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/iana-time-zone-0.1/debian/patches/fix-windows-dep.patch [new file with mode: 0644]
tests/configs/iana-time-zone-0.1/debian/patches/series [new file with mode: 0644]
tests/configs/jetscii-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/jetscii-0.3/debian/rules [new file with mode: 0644]
tests/configs/kqueue-1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/kqueue-1/debian/rules [new file with mode: 0644]
tests/configs/kqueue-sys-1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/kqueue-sys-1/debian/rules [new file with mode: 0644]
tests/configs/libdav1d-sys-0.6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/libdbus-sys-0.2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/mysqlclient-src-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/mysqlclient-sys-0.2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/mysqlclient-sys-0.4/debian/debcargo.toml [new file with mode: 0644]
tests/configs/nasm-rs-0.2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/netlib-src-0.8/debian/debcargo.toml [new file with mode: 0644]
tests/configs/nodrop-union-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/nodrop-union-0.1/debian/rules [new file with mode: 0644]
tests/configs/nom-4/debian/debcargo.toml [new file with mode: 0644]
tests/configs/nom-4/debian/rules [new file with mode: 0644]
tests/configs/old-version/debian/debcargo.toml [new file with mode: 0644]
tests/configs/once-cell-1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/onig-6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/onig-6/debian/rules [new file with mode: 0644]
tests/configs/onig-sys-69/debian/debcargo.toml [new file with mode: 0644]
tests/configs/onig-sys-69/debian/rules [new file with mode: 0644]
tests/configs/only-macos/debian/debcargo.toml [new file with mode: 0644]
tests/configs/only-macos/debian/rules [new file with mode: 0644]
tests/configs/only-windows/debian/debcargo.toml [new file with mode: 0644]
tests/configs/only-windows/debian/rules [new file with mode: 0644]
tests/configs/openssl-sys-0.9/debian/debcargo.toml [new file with mode: 0644]
tests/configs/openssl-sys-0.9/debian/patches/disable-bssl.patch [new file with mode: 0644]
tests/configs/openssl-sys-0.9/debian/patches/series [new file with mode: 0644]
tests/configs/packed-simd-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/packed-simd-0.3/debian/rules [new file with mode: 0644]
tests/configs/packed-simd-2-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/packed-simd-2-0.3/debian/rules [new file with mode: 0644]
tests/configs/petgraph-0.4/debian/debcargo.toml [new file with mode: 0644]
tests/configs/petgraph-0.4/debian/patches/fix-old-dep.patch [new file with mode: 0644]
tests/configs/petgraph-0.4/debian/patches/series [new file with mode: 0644]
tests/configs/phf-generator-0.10/debian/debcargo.toml [new file with mode: 0644]
tests/configs/pkg-config-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/rav1e-0.6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/rav1e-0.6/debian/patches/relax-clap.diff [new file with mode: 0644]
tests/configs/rav1e-0.6/debian/patches/series [new file with mode: 0644]
tests/configs/redis-0.17/debian/debcargo.toml [new file with mode: 0644]
tests/configs/redis-0.17/debian/rules [new file with mode: 0644]
tests/configs/redox-syscall-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/redox-syscall-0.1/debian/rules [new file with mode: 0644]
tests/configs/redox-users-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/redox-users-0.3/debian/rules [new file with mode: 0644]
tests/configs/rhai-1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/rhai-1/debian/rules [new file with mode: 0644]
tests/configs/ring-0.13/debian/debcargo.toml [new file with mode: 0644]
tests/configs/ring-0.13/debian/rules [new file with mode: 0644]
tests/configs/ring-0.14/debian/debcargo.toml [new file with mode: 0644]
tests/configs/ring-0.14/debian/rules [new file with mode: 0644]
tests/configs/rust-hawktracer-sys-0.4/debian/debcargo.toml [new file with mode: 0644]
tests/configs/rust-hawktracer-sys-0.4/debian/rules [new file with mode: 0644]
tests/configs/rust-lzma-0.5/debian/debcargo.toml [new file with mode: 0644]
tests/configs/salvo-extra-0.16/debian/debcargo.toml [new file with mode: 0644]
tests/configs/salvo-extra-0.16/debian/rules [new file with mode: 0644]
tests/configs/security-framework-2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/security-framework-2/debian/rules [new file with mode: 0644]
tests/configs/security-framework-sys-2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/security-framework-sys-2/debian/rules [new file with mode: 0644]
tests/configs/serde-qs-0.8/debian/debcargo.toml [new file with mode: 0644]
tests/configs/serde-qs-0.8/debian/patches/fix-actix-web-dep.patch [new file with mode: 0644]
tests/configs/serde-qs-0.8/debian/patches/series [new file with mode: 0644]
tests/configs/servo-fontconfig-sys-5/debian/debcargo.toml [new file with mode: 0644]
tests/configs/sleef-sys-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/sleef-sys-0.1/debian/rules [new file with mode: 0644]
tests/configs/spin-0.4/debian/debcargo.toml [new file with mode: 0644]
tests/configs/spin-0.4/debian/rules [new file with mode: 0644]
tests/configs/structopt-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/structopt-0.3/debian/patches/disable-lint-feature.diff [new file with mode: 0644]
tests/configs/structopt-0.3/debian/patches/disable-paw.diff [new file with mode: 0644]
tests/configs/structopt-0.3/debian/patches/series [new file with mode: 0644]
tests/configs/system-configuration-0.5/debian/debcargo.toml [new file with mode: 0644]
tests/configs/system-configuration-0.5/debian/rules [new file with mode: 0644]
tests/configs/system-configuration-0.6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/system-configuration-0.6/debian/rules [new file with mode: 0644]
tests/configs/system-configuration-sys-0.5/debian/debcargo.toml [new file with mode: 0644]
tests/configs/system-configuration-sys-0.5/debian/rules [new file with mode: 0644]
tests/configs/system-configuration-sys-0.6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/system-configuration-sys-0.6/debian/rules [new file with mode: 0644]
tests/configs/system-deps-6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/system-deps-6/debian/rules [new file with mode: 0755]
tests/configs/tiny-keccak-2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/tiny-keccak-2/debian/rules [new file with mode: 0644]
tests/configs/vcpkg-0.2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/wepoll-ffi-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/wepoll-ffi-0.1/debian/rules [new file with mode: 0644]
tests/configs/windows-0.32/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-0.32/debian/rules [new file with mode: 0644]
tests/configs/windows-0.48/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-0.48/debian/rules [new file with mode: 0644]
tests/configs/windows-0.54/debian/changelog [new file with mode: 0644]
tests/configs/windows-0.54/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-0.54/debian/patches/remove-cycles.patch [new file with mode: 0644]
tests/configs/windows-0.54/debian/patches/series [new file with mode: 0644]
tests/configs/windows-0.54/debian/rules [new file with mode: 0644]
tests/configs/windows-0.54/debian/rules.debcargo.hint [new file with mode: 0755]
tests/configs/windows-0.58/debian/changelog [new file with mode: 0644]
tests/configs/windows-0.58/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-0.58/debian/patches/remove-cycles.patch [new file with mode: 0644]
tests/configs/windows-0.58/debian/patches/remove-cycles.patch~ [new file with mode: 0644]
tests/configs/windows-0.58/debian/patches/series [new file with mode: 0644]
tests/configs/windows-0.58/debian/rules [new file with mode: 0644]
tests/configs/windows-0.58/debian/rules.debcargo.hint [new file with mode: 0755]
tests/configs/windows-i686-gnullvm-0.52/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-i686-gnullvm-0.52/debian/rules [new file with mode: 0755]
tests/configs/windows-sys-0.59/debian/changelog [new file with mode: 0644]
tests/configs/windows-sys-0.59/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-sys-0.59/debian/patches/remove-cycles.patch [new file with mode: 0644]
tests/configs/windows-sys-0.59/debian/patches/series [new file with mode: 0644]
tests/configs/windows-sys-0.59/debian/rules [new file with mode: 0644]
tests/configs/windows-sys-0.59/debian/rules.debcargo.hint [new file with mode: 0755]
tests/configs/windows-x86-64-gnullvm-0.42/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-x86-64-gnullvm-0.42/debian/rules [new file with mode: 0755]
tests/configs/windows-x86-64-gnullvm-0.48/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-x86-64-gnullvm-0.48/debian/rules [new file with mode: 0755]
tests/configs/windows-x86-64-gnullvm-0.52/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-x86-64-gnullvm-0.52/debian/rules [new file with mode: 0755]
tests/configs/winreg-0.10/debian/debcargo.toml [new file with mode: 0644]
tests/configs/winreg-0.10/debian/rules [new file with mode: 0644]
tests/configs/winreg-0.50/debian/debcargo.toml [new file with mode: 0644]
tests/configs/winreg-0.50/debian/rules [new file with mode: 0644]
tests/configs/winreg-0.6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/winreg-0.6/debian/rules [new file with mode: 0644]
tests/configs/x86-0.33/debian/debcargo.toml [new file with mode: 0644]
tests/configs/x86-0.33/debian/rules [new file with mode: 0644]
tests/configs/yeslogic-fontconfig-sys-6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/zip-0.5/debian/debcargo.toml [new file with mode: 0644]
tests/configs/zip-0.6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/zip/debian/debcargo.toml [new file with mode: 0644]
tests/debcargo_override.toml [new file with mode: 0644]
tests/debcargo_override_top_level.toml [new file with mode: 0644]
tests/foobar-overlay/debian/debcargo.toml [new file with mode: 0644]
tests/foobar-semver-overlay/debian/debcargo.toml [new file with mode: 0644]
tests/foobar-semver.expected [new file with mode: 0644]
tests/foobar.expected [new file with mode: 0644]
tests/local-crate.rs [new file with mode: 0644]
tests/manpages.rs [new file with mode: 0644]
tests/sh/integrate.sh [new file with mode: 0755]
tests/sh/lintian-suppress-tags [new file with mode: 0644]
tests/sh/quick-build.sh [new file with mode: 0755]
tests/tiny-dfr_override.toml [new file with mode: 0644]

diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644 (file)
index 0000000..f534867
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "git": {
+    "sha1": "83479ffeac1eb03178387c3ddf8b68bc2e585aac"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..8f6d9c7
--- /dev/null
@@ -0,0 +1,10 @@
+/target
+/tmp
+
+/tests/foobar/target
+/tests/foobar-semver/target
+
+# editor files
+*~
+.idea/
+*.kdev4
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644 (file)
index 0000000..dfe9ac3
--- /dev/null
@@ -0,0 +1,20 @@
+image: "rust:latest"
+
+test:cargo:
+  script:
+    - rustc --version && cargo --version  # Print version info for debugging
+    - cargo test --workspace --verbose
+
+test:clippy:
+  stage: test
+  before_script:
+    - rustup component add clippy
+  script:
+    - cargo clippy
+
+test:format-code:
+  stage: test
+  before_script:
+    - rustup component add rustfmt
+  script:
+    - cargo fmt -- --check
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644 (file)
index 0000000..fbba204
--- /dev/null
@@ -0,0 +1,4414 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "adler2"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "allocator-api2"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "annotate-snippets"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4"
+dependencies = [
+ "anstyle",
+ "unicode-width",
+]
+
+[[package]]
+name = "anstream"
+version = "0.6.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
+dependencies = [
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
+dependencies = [
+ "anstyle",
+ "once_cell_polyfill",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
+
+[[package]]
+name = "arc-swap"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
+
+[[package]]
+name = "arrayref"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
+
+[[package]]
+name = "arrayvec"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
+
+[[package]]
+name = "autocfg"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
+
+[[package]]
+name = "base16ct"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
+
+[[package]]
+name = "base64"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
+[[package]]
+name = "base64ct"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a"
+
+[[package]]
+name = "bitflags"
+version = "2.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
+
+[[package]]
+name = "bitmaps"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "blake3"
+version = "1.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0"
+dependencies = [
+ "arrayref",
+ "arrayvec",
+ "cc",
+ "cfg-if",
+ "constant_time_eq",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "block2"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
+dependencies = [
+ "objc2",
+]
+
+[[package]]
+name = "bstr"
+version = "1.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
+dependencies = [
+ "memchr",
+ "regex-automata",
+ "serde",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.19.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
+
+[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
+name = "bytes"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
+
+[[package]]
+name = "cargo"
+version = "0.91.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f46c7f53180bf46c220e2af1ceff951e2ce088184fa9009ad6915efee25915d"
+dependencies = [
+ "annotate-snippets",
+ "anstream",
+ "anstyle",
+ "anyhow",
+ "base64",
+ "blake3",
+ "cargo-credential",
+ "cargo-credential-libsecret",
+ "cargo-credential-macos-keychain",
+ "cargo-credential-wincred",
+ "cargo-platform",
+ "cargo-util",
+ "cargo-util-schemas",
+ "clap",
+ "clap_complete",
+ "color-print",
+ "crates-io",
+ "curl",
+ "curl-sys",
+ "filetime",
+ "flate2",
+ "git2",
+ "git2-curl",
+ "gix",
+ "glob",
+ "hex",
+ "hmac",
+ "home",
+ "http-auth",
+ "ignore",
+ "im-rc",
+ "indexmap",
+ "itertools 0.14.0",
+ "jiff",
+ "jobserver",
+ "lazycell",
+ "libc",
+ "libgit2-sys",
+ "memchr",
+ "opener",
+ "os_info",
+ "pasetors",
+ "pathdiff",
+ "rand",
+ "regex",
+ "rusqlite",
+ "rustc-hash 2.1.1",
+ "rustc-stable-hash",
+ "rustfix",
+ "same-file",
+ "semver",
+ "serde",
+ "serde-untagged",
+ "serde_ignored",
+ "serde_json",
+ "sha1",
+ "shell-escape",
+ "supports-hyperlinks",
+ "supports-unicode",
+ "tar",
+ "tempfile",
+ "thiserror",
+ "time",
+ "toml 0.9.9+spec-1.0.0",
+ "toml_edit 0.23.10+spec-1.0.0",
+ "tracing",
+ "tracing-chrome",
+ "tracing-subscriber",
+ "unicase",
+ "unicode-width",
+ "unicode-xid",
+ "url",
+ "walkdir",
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "cargo-credential"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e36f089041deadf16226478a7737a833864fbda09408c7af237b9d615eeb6d69"
+dependencies = [
+ "anyhow",
+ "libc",
+ "serde",
+ "serde_json",
+ "thiserror",
+ "time",
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "cargo-credential-libsecret"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67e287f3cc9732b9a7eb5140e9501ec6557bdcdc83366a424993e4d4db228c4a"
+dependencies = [
+ "anyhow",
+ "cargo-credential",
+ "libloading",
+]
+
+[[package]]
+name = "cargo-credential-macos-keychain"
+version = "0.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "806cb58d7644f7c4f8c8e47af5f7f2dc4e10f0ce205f0416e8fdc6d58c7efaf2"
+dependencies = [
+ "cargo-credential",
+ "security-framework",
+]
+
+[[package]]
+name = "cargo-credential-wincred"
+version = "0.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a12eac22936a44d4be4765ffb9a29cbd69faab267a637c578feef62f8cc96c39"
+dependencies = [
+ "cargo-credential",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87a0c0e6148f11f01f32650a2ea02d532b2ad4e81d8bd41e6e565b5adc5e6082"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "cargo-util"
+version = "0.2.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03ae3fc62640c9e0235c95b07e68a59a31919d7331bd95961cc811bc0607c87b"
+dependencies = [
+ "anyhow",
+ "core-foundation",
+ "filetime",
+ "hex",
+ "ignore",
+ "jobserver",
+ "libc",
+ "miow",
+ "same-file",
+ "sha2",
+ "shell-escape",
+ "tempfile",
+ "tracing",
+ "walkdir",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "cargo-util-schemas"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f714efe9b56ea4bed06b499396e77b68db663a55b16dc3f144d5a5a0dc19788c"
+dependencies = [
+ "semver",
+ "serde",
+ "serde-untagged",
+ "serde-value",
+ "thiserror",
+ "toml 0.9.9+spec-1.0.0",
+ "unicode-xid",
+ "url",
+]
+
+[[package]]
+name = "cc"
+version = "1.2.49"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215"
+dependencies = [
+ "find-msvc-tools",
+ "jobserver",
+ "libc",
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
+
+[[package]]
+name = "cfg_aliases"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+
+[[package]]
+name = "chrono"
+version = "0.4.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
+dependencies = [
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "wasm-bindgen",
+ "windows-link",
+]
+
+[[package]]
+name = "clap"
+version = "4.5.53"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.53"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+ "terminal_size",
+]
+
+[[package]]
+name = "clap_complete"
+version = "4.5.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39615915e2ece2550c0149addac32fb5bd312c657f43845bb9088cb9c8a7c992"
+dependencies = [
+ "clap",
+ "clap_lex",
+ "is_executable",
+ "shlex",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.49"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
+
+[[package]]
+name = "clap_mangen"
+version = "0.2.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ea63a92086df93893164221ad4f24142086d535b3a0957b9b9bea2dc86301"
+dependencies = [
+ "clap",
+ "roff",
+]
+
+[[package]]
+name = "clru"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59"
+
+[[package]]
+name = "color-print"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3aa954171903797d5623e047d9ab69d91b493657917bdfb8c2c80ecaf9cdb6f4"
+dependencies = [
+ "color-print-proc-macro",
+]
+
+[[package]]
+name = "color-print-proc-macro"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "692186b5ebe54007e45a59aea47ece9eb4108e141326c304cdc91699a7118a22"
+dependencies = [
+ "nom",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "colorchoice"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
+
+[[package]]
+name = "const-oid"
+version = "0.9.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
+
+[[package]]
+name = "constant_time_eq"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
+
+[[package]]
+name = "core-foundation"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
+[[package]]
+name = "countme"
+version = "3.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crates-io"
+version = "0.40.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62451b814867f57f25e941eeb22b55ada9d93308cb65578ec57e35e414091019"
+dependencies = [
+ "curl",
+ "percent-encoding",
+ "serde",
+ "serde_json",
+ "thiserror",
+ "url",
+]
+
+[[package]]
+name = "crc32fast"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
+
+[[package]]
+name = "crypto-bigint"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
+dependencies = [
+ "generic-array",
+ "rand_core 0.6.4",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "ct-codecs"
+version = "1.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b10589d1a5e400d61f9f38f12f884cfd080ff345de8f17efda36fe0e4a02aa8"
+
+[[package]]
+name = "curl"
+version = "0.4.49"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79fc3b6dd0b87ba36e565715bf9a2ced221311db47bd18011676f24a6066edbc"
+dependencies = [
+ "curl-sys",
+ "libc",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "socket2",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "curl-sys"
+version = "0.4.84+curl-8.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abc4294dc41b882eaff37973c2ec3ae203d0091341ee68fbadd1d06e0c18a73b"
+dependencies = [
+ "cc",
+ "libc",
+ "libnghttp2-sys",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+ "vcpkg",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "dashmap"
+version = "6.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+ "hashbrown 0.14.5",
+ "lock_api",
+ "once_cell",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "deb822-derive"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e83ef29a094bcb2b7dd0f609ace7f5a34ef9a62e0731ebd350637640320a3b15"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "deb822-fast"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "114c474fa4cd5d6d24bb5e68b36fa4ef70f5b830e3cc14a9b66a12e71a15aeb9"
+dependencies = [
+ "deb822-derive",
+]
+
+[[package]]
+name = "deb822-lossless"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4b7d08154e599ffe6652ff71969763c70a93e2acc3cd9c274e576028fddd4f1"
+dependencies = [
+ "regex",
+ "rowan",
+ "serde",
+]
+
+[[package]]
+name = "debcargo"
+version = "2.8.1"
+dependencies = [
+ "anyhow",
+ "cargo",
+ "cargo-util",
+ "cargo-util-schemas",
+ "chrono",
+ "clap",
+ "clap_mangen",
+ "debian-control",
+ "env_logger",
+ "filetime",
+ "flate2",
+ "git2",
+ "glob",
+ "itertools 0.13.0",
+ "log",
+ "nu-ansi-term",
+ "regex",
+ "semver",
+ "serde",
+ "serde_derive",
+ "tar",
+ "tempfile",
+ "textwrap",
+ "toml 0.8.23",
+ "walkdir",
+]
+
+[[package]]
+name = "debian-control"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8b602c78f6bb49bcf00320a3144a0de52b622d085ab4aa02187722141ac1297"
+dependencies = [
+ "deb822-fast",
+ "deb822-lossless",
+ "debversion",
+ "regex",
+ "rowan",
+ "url",
+]
+
+[[package]]
+name = "debversion"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4f5cc9ce1d5067bee8060dd75208525dd0133ffea0b2960fef64ab85d58c4c5"
+dependencies = [
+ "chrono",
+ "lazy-regex",
+ "num-bigint",
+]
+
+[[package]]
+name = "der"
+version = "0.7.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
+dependencies = [
+ "const-oid",
+ "pem-rfc7468",
+ "zeroize",
+]
+
+[[package]]
+name = "deranged"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587"
+dependencies = [
+ "powerfmt",
+ "serde_core",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "const-oid",
+ "crypto-common",
+ "subtle",
+]
+
+[[package]]
+name = "dispatch2"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
+dependencies = [
+ "bitflags",
+ "objc2",
+]
+
+[[package]]
+name = "displaydoc"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "dunce"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
+
+[[package]]
+name = "ecdsa"
+version = "0.16.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
+dependencies = [
+ "der",
+ "digest",
+ "elliptic-curve",
+ "rfc6979",
+ "signature",
+ "spki",
+]
+
+[[package]]
+name = "ed25519-compact"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ce99a9e19c84beb4cc35ece85374335ccc398240712114c85038319ed709bd"
+dependencies = [
+ "getrandom 0.3.4",
+]
+
+[[package]]
+name = "either"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
+[[package]]
+name = "elliptic-curve"
+version = "0.13.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
+dependencies = [
+ "base16ct",
+ "crypto-bigint",
+ "digest",
+ "ff",
+ "generic-array",
+ "group",
+ "hkdf",
+ "pem-rfc7468",
+ "pkcs8",
+ "rand_core 0.6.4",
+ "sec1",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "encoding_rs"
+version = "0.8.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "env_filter"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2"
+dependencies = [
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.11.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "env_filter",
+ "jiff",
+ "log",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
+name = "erased-serde"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89e8918065695684b2b0702da20382d5ae6065cf3327bc2d6436bd49a71ce9f3"
+dependencies = [
+ "serde",
+ "serde_core",
+ "typeid",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
+dependencies = [
+ "libc",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "fallible-iterator"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
+
+[[package]]
+name = "fallible-streaming-iterator"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
+
+[[package]]
+name = "faster-hex"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7223ae2d2f179b803433d9c830478527e92b8117eab39460edae7f1614d9fb73"
+dependencies = [
+ "heapless",
+ "serde",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
+
+[[package]]
+name = "ff"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393"
+dependencies = [
+ "rand_core 0.6.4",
+ "subtle",
+]
+
+[[package]]
+name = "fiat-crypto"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24"
+
+[[package]]
+name = "filetime"
+version = "0.2.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "libredox",
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "find-msvc-tools"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844"
+
+[[package]]
+name = "flate2"
+version = "1.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
+dependencies = [
+ "crc32fast",
+ "libz-rs-sys",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "foldhash"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
+dependencies = [
+ "typenum",
+ "version_check",
+ "zeroize",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "libc",
+ "r-efi",
+ "wasip2",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "git2"
+version = "0.20.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e2b37e2f62729cdada11f0e6b3b6fe383c69c29fc619e391223e12856af308c"
+dependencies = [
+ "bitflags",
+ "libc",
+ "libgit2-sys",
+ "log",
+ "openssl-probe",
+ "openssl-sys",
+ "url",
+]
+
+[[package]]
+name = "git2-curl"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be8dcabbc09ece4d30a9aa983d5804203b7e2f8054a171f792deff59b56d31fa"
+dependencies = [
+ "curl",
+ "git2",
+ "log",
+ "url",
+]
+
+[[package]]
+name = "gix"
+version = "0.73.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "514c29cc879bdc0286b0cbc205585a49b252809eb86c69df4ce4f855ee75f635"
+dependencies = [
+ "gix-actor",
+ "gix-attributes",
+ "gix-command",
+ "gix-commitgraph",
+ "gix-config",
+ "gix-credentials",
+ "gix-date",
+ "gix-diff",
+ "gix-dir",
+ "gix-discover",
+ "gix-features",
+ "gix-filter",
+ "gix-fs",
+ "gix-glob",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-ignore",
+ "gix-index",
+ "gix-lock",
+ "gix-negotiate",
+ "gix-object",
+ "gix-odb",
+ "gix-pack",
+ "gix-path",
+ "gix-pathspec",
+ "gix-prompt",
+ "gix-protocol",
+ "gix-ref",
+ "gix-refspec",
+ "gix-revision",
+ "gix-revwalk",
+ "gix-sec",
+ "gix-shallow",
+ "gix-status",
+ "gix-submodule",
+ "gix-tempfile",
+ "gix-trace",
+ "gix-transport",
+ "gix-traverse",
+ "gix-url",
+ "gix-utils",
+ "gix-validate",
+ "gix-worktree",
+ "once_cell",
+ "prodash",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-actor"
+version = "0.35.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "987a51a7e66db6ef4dc030418eb2a42af6b913a79edd8670766122d8af3ba59e"
+dependencies = [
+ "bstr",
+ "gix-date",
+ "gix-utils",
+ "itoa",
+ "thiserror",
+ "winnow",
+]
+
+[[package]]
+name = "gix-attributes"
+version = "0.27.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45442188216d08a5959af195f659cb1f244a50d7d2d0c3873633b1cd7135f638"
+dependencies = [
+ "bstr",
+ "gix-glob",
+ "gix-path",
+ "gix-quote",
+ "gix-trace",
+ "kstring",
+ "smallvec",
+ "thiserror",
+ "unicode-bom",
+]
+
+[[package]]
+name = "gix-bitmap"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e150161b8a75b5860521cb876b506879a3376d3adc857ec7a9d35e7c6a5e531"
+dependencies = [
+ "thiserror",
+]
+
+[[package]]
+name = "gix-chunk"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c356b3825677cb6ff579551bb8311a81821e184453cbd105e2fc5311b288eeb"
+dependencies = [
+ "thiserror",
+]
+
+[[package]]
+name = "gix-command"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "095c8367c9dc4872a7706fbc39c7f34271b88b541120a4365ff0e36366f66e62"
+dependencies = [
+ "bstr",
+ "gix-path",
+ "gix-quote",
+ "gix-trace",
+ "shell-words",
+]
+
+[[package]]
+name = "gix-commitgraph"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bb23121e952f43a5b07e3e80890336cb847297467a410475036242732980d06"
+dependencies = [
+ "bstr",
+ "gix-chunk",
+ "gix-hash",
+ "memmap2",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-config"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dfb898c5b695fd4acfc3c0ab638525a65545d47706064dcf7b5ead6cdb136c0"
+dependencies = [
+ "bstr",
+ "gix-config-value",
+ "gix-features",
+ "gix-glob",
+ "gix-path",
+ "gix-ref",
+ "gix-sec",
+ "memchr",
+ "once_cell",
+ "smallvec",
+ "thiserror",
+ "unicode-bom",
+ "winnow",
+]
+
+[[package]]
+name = "gix-config-value"
+version = "0.15.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c489abb061c74b0c3ad790e24a606ef968cebab48ec673d6a891ece7d5aef64"
+dependencies = [
+ "bitflags",
+ "bstr",
+ "gix-path",
+ "libc",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-credentials"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0039dd3ac606dd80b16353a41b61fc237ca5cb8b612f67a9f880adfad4be4e05"
+dependencies = [
+ "bstr",
+ "gix-command",
+ "gix-config-value",
+ "gix-date",
+ "gix-path",
+ "gix-prompt",
+ "gix-sec",
+ "gix-trace",
+ "gix-url",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-date"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "661245d045aa7c16ba4244daaabd823c562c3e45f1f25b816be2c57ee09f2171"
+dependencies = [
+ "bstr",
+ "itoa",
+ "jiff",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-diff"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de854852010d44a317f30c92d67a983e691c9478c8a3fb4117c1f48626bcdea8"
+dependencies = [
+ "bstr",
+ "gix-attributes",
+ "gix-command",
+ "gix-filter",
+ "gix-fs",
+ "gix-hash",
+ "gix-index",
+ "gix-object",
+ "gix-path",
+ "gix-pathspec",
+ "gix-tempfile",
+ "gix-trace",
+ "gix-traverse",
+ "gix-worktree",
+ "imara-diff",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-dir"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dad34e4f373f94902df1ba1d2a1df3a1b29eacd15e316ac5972d842e31422dd7"
+dependencies = [
+ "bstr",
+ "gix-discover",
+ "gix-fs",
+ "gix-ignore",
+ "gix-index",
+ "gix-object",
+ "gix-path",
+ "gix-pathspec",
+ "gix-trace",
+ "gix-utils",
+ "gix-worktree",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-discover"
+version = "0.41.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffb180c91ca1a2cf53e828bb63d8d8f8fa7526f49b83b33d7f46cbeb5d79d30a"
+dependencies = [
+ "bstr",
+ "dunce",
+ "gix-fs",
+ "gix-hash",
+ "gix-path",
+ "gix-ref",
+ "gix-sec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-features"
+version = "0.43.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd1543cd9b8abcbcebaa1a666a5c168ee2cda4dea50d3961ee0e6d1c42f81e5b"
+dependencies = [
+ "bytes",
+ "crc32fast",
+ "crossbeam-channel",
+ "flate2",
+ "gix-path",
+ "gix-trace",
+ "gix-utils",
+ "libc",
+ "once_cell",
+ "parking_lot",
+ "prodash",
+ "thiserror",
+ "walkdir",
+]
+
+[[package]]
+name = "gix-filter"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa6571a3927e7ab10f64279a088e0dae08e8da05547771796d7389bbe28ad9ff"
+dependencies = [
+ "bstr",
+ "encoding_rs",
+ "gix-attributes",
+ "gix-command",
+ "gix-hash",
+ "gix-object",
+ "gix-packetline-blocking",
+ "gix-path",
+ "gix-quote",
+ "gix-trace",
+ "gix-utils",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-fs"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a4d90307d064fa7230e0f87b03231be28f8ba63b913fc15346f489519d0c304"
+dependencies = [
+ "bstr",
+ "fastrand",
+ "gix-features",
+ "gix-path",
+ "gix-utils",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-glob"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b947db8366823e7a750c254f6bb29e27e17f27e457bf336ba79b32423db62cd5"
+dependencies = [
+ "bitflags",
+ "bstr",
+ "gix-features",
+ "gix-path",
+]
+
+[[package]]
+name = "gix-hash"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "251fad79796a731a2a7664d9ea95ee29a9e99474de2769e152238d4fdb69d50e"
+dependencies = [
+ "faster-hex",
+ "gix-features",
+ "sha1-checked",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-hashtable"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c35300b54896153e55d53f4180460931ccd69b7e8d2f6b9d6401122cdedc4f07"
+dependencies = [
+ "gix-hash",
+ "hashbrown 0.15.5",
+ "parking_lot",
+]
+
+[[package]]
+name = "gix-ignore"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "564d6fddf46e2c981f571b23d6ad40cb08bddcaf6fc7458b1d49727ad23c2870"
+dependencies = [
+ "bstr",
+ "gix-glob",
+ "gix-path",
+ "gix-trace",
+ "unicode-bom",
+]
+
+[[package]]
+name = "gix-index"
+version = "0.41.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2af39fde3ce4ce11371d9ce826f2936ec347318f2d1972fe98c2e7134e267e25"
+dependencies = [
+ "bitflags",
+ "bstr",
+ "filetime",
+ "fnv",
+ "gix-bitmap",
+ "gix-features",
+ "gix-fs",
+ "gix-hash",
+ "gix-lock",
+ "gix-object",
+ "gix-traverse",
+ "gix-utils",
+ "gix-validate",
+ "hashbrown 0.15.5",
+ "itoa",
+ "libc",
+ "memmap2",
+ "rustix",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-lock"
+version = "18.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9fa71da90365668a621e184eb5b979904471af1b3b09b943a84bc50e8ad42ed"
+dependencies = [
+ "gix-tempfile",
+ "gix-utils",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-negotiate"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d58d4c9118885233be971e0d7a589f5cfb1a8bd6cb6e2ecfb0fc6b1b293c83b"
+dependencies = [
+ "bitflags",
+ "gix-commitgraph",
+ "gix-date",
+ "gix-hash",
+ "gix-object",
+ "gix-revwalk",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-object"
+version = "0.50.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d69ce108ab67b65fbd4fb7e1331502429d78baeb2eee10008bdef55765397c07"
+dependencies = [
+ "bstr",
+ "gix-actor",
+ "gix-date",
+ "gix-features",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-path",
+ "gix-utils",
+ "gix-validate",
+ "itoa",
+ "smallvec",
+ "thiserror",
+ "winnow",
+]
+
+[[package]]
+name = "gix-odb"
+version = "0.70.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c9d7af10fda9df0bb4f7f9bd507963560b3c66cb15a5b825caf752e0eb109ac"
+dependencies = [
+ "arc-swap",
+ "gix-date",
+ "gix-features",
+ "gix-fs",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
+ "gix-pack",
+ "gix-path",
+ "gix-quote",
+ "parking_lot",
+ "tempfile",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-pack"
+version = "0.60.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8571df89bfca5abb49c3e3372393f7af7e6f8b8dbe2b96303593cef5b263019"
+dependencies = [
+ "clru",
+ "gix-chunk",
+ "gix-features",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
+ "gix-path",
+ "gix-tempfile",
+ "memmap2",
+ "parking_lot",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-packetline"
+version = "0.19.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64286a8b5148e76ab80932e72762dd27ccf6169dd7a134b027c8a262a8262fcf"
+dependencies = [
+ "bstr",
+ "faster-hex",
+ "gix-trace",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-packetline-blocking"
+version = "0.19.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89c59c3ad41e68cb38547d849e9ef5ccfc0d00f282244ba1441ae856be54d001"
+dependencies = [
+ "bstr",
+ "faster-hex",
+ "gix-trace",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-path"
+version = "0.10.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cb06c3e4f8eed6e24fd915fa93145e28a511f4ea0e768bae16673e05ed3f366"
+dependencies = [
+ "bstr",
+ "gix-trace",
+ "gix-validate",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-pathspec"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "daedead611c9bd1f3640dc90a9012b45f790201788af4d659f28d94071da7fba"
+dependencies = [
+ "bitflags",
+ "bstr",
+ "gix-attributes",
+ "gix-config-value",
+ "gix-glob",
+ "gix-path",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-prompt"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "868e6516dfa16fdcbc5f8c935167d085f2ae65ccd4c9476a4319579d12a69d8d"
+dependencies = [
+ "gix-command",
+ "gix-config-value",
+ "parking_lot",
+ "rustix",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-protocol"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12b4b807c47ffcf7c1e5b8119585368a56449f3493da93b931e1d4239364e922"
+dependencies = [
+ "bstr",
+ "gix-credentials",
+ "gix-date",
+ "gix-features",
+ "gix-hash",
+ "gix-lock",
+ "gix-negotiate",
+ "gix-object",
+ "gix-ref",
+ "gix-refspec",
+ "gix-revwalk",
+ "gix-shallow",
+ "gix-trace",
+ "gix-transport",
+ "gix-utils",
+ "maybe-async",
+ "thiserror",
+ "winnow",
+]
+
+[[package]]
+name = "gix-quote"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e912ec04b7b1566a85ad486db0cab6b9955e3e32bcd3c3a734542ab3af084c5b"
+dependencies = [
+ "bstr",
+ "gix-utils",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-ref"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b966f578079a42f4a51413b17bce476544cca1cf605753466669082f94721758"
+dependencies = [
+ "gix-actor",
+ "gix-features",
+ "gix-fs",
+ "gix-hash",
+ "gix-lock",
+ "gix-object",
+ "gix-path",
+ "gix-tempfile",
+ "gix-utils",
+ "gix-validate",
+ "memmap2",
+ "thiserror",
+ "winnow",
+]
+
+[[package]]
+name = "gix-refspec"
+version = "0.31.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d29cae1ae31108826e7156a5e60bffacab405f4413f5bc0375e19772cce0055"
+dependencies = [
+ "bstr",
+ "gix-hash",
+ "gix-revision",
+ "gix-validate",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-revision"
+version = "0.35.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f651f2b1742f760bb8161d6743229206e962b73d9c33c41f4e4aefa6586cbd3d"
+dependencies = [
+ "bstr",
+ "gix-commitgraph",
+ "gix-date",
+ "gix-hash",
+ "gix-object",
+ "gix-revwalk",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-revwalk"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06e74f91709729e099af6721bd0fa7d62f243f2005085152301ca5cdd86ec02c"
+dependencies = [
+ "gix-commitgraph",
+ "gix-date",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-sec"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea9962ed6d9114f7f100efe038752f41283c225bb507a2888903ac593dffa6be"
+dependencies = [
+ "bitflags",
+ "gix-path",
+ "libc",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "gix-shallow"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d936745103243ae4c510f19e0760ce73fb0f08096588fdbe0f0d7fb7ce8944b7"
+dependencies = [
+ "bstr",
+ "gix-hash",
+ "gix-lock",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-status"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a4afff9b34eeececa8bdc32b42fb318434b6b1391d9f8d45fe455af08dc2d35"
+dependencies = [
+ "bstr",
+ "filetime",
+ "gix-diff",
+ "gix-dir",
+ "gix-features",
+ "gix-filter",
+ "gix-fs",
+ "gix-hash",
+ "gix-index",
+ "gix-object",
+ "gix-path",
+ "gix-pathspec",
+ "gix-worktree",
+ "portable-atomic",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-submodule"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "657cc5dd43cbc7a14d9c5aaf02cfbe9c2a15d077cded3f304adb30ef78852d3e"
+dependencies = [
+ "bstr",
+ "gix-config",
+ "gix-path",
+ "gix-pathspec",
+ "gix-refspec",
+ "gix-url",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-tempfile"
+version = "18.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "666c0041bcdedf5fa05e9bef663c897debab24b7dc1741605742412d1d47da57"
+dependencies = [
+ "dashmap",
+ "gix-fs",
+ "libc",
+ "once_cell",
+ "parking_lot",
+ "tempfile",
+]
+
+[[package]]
+name = "gix-trace"
+version = "0.1.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d3f59a8de2934f6391b6b3a1a7654eae18961fcb9f9c843533fed34ad0f3457"
+
+[[package]]
+name = "gix-transport"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12f7cc0179fc89d53c54e1f9ce51229494864ab4bf136132d69db1b011741ca3"
+dependencies = [
+ "base64",
+ "bstr",
+ "curl",
+ "gix-command",
+ "gix-credentials",
+ "gix-features",
+ "gix-packetline",
+ "gix-quote",
+ "gix-sec",
+ "gix-url",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-traverse"
+version = "0.47.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7cdc82509d792ba0ad815f86f6b469c7afe10f94362e96c4494525a6601bdd5"
+dependencies = [
+ "bitflags",
+ "gix-commitgraph",
+ "gix-date",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
+ "gix-revwalk",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-url"
+version = "0.32.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b76a9d266254ad287ffd44467cd88e7868799b08f4d52e02d942b93e514d16f"
+dependencies = [
+ "bstr",
+ "gix-features",
+ "gix-path",
+ "percent-encoding",
+ "thiserror",
+ "url",
+]
+
+[[package]]
+name = "gix-utils"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "befcdbdfb1238d2854591f760a48711bed85e72d80a10e8f2f93f656746ef7c5"
+dependencies = [
+ "bstr",
+ "fastrand",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "gix-validate"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b1e63a5b516e970a594f870ed4571a8fdcb8a344e7bd407a20db8bd61dbfde4"
+dependencies = [
+ "bstr",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-worktree"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55f625ac9126c19bef06dbc6d2703cdd7987e21e35b497bb265ac37d383877b1"
+dependencies = [
+ "bstr",
+ "gix-attributes",
+ "gix-features",
+ "gix-fs",
+ "gix-glob",
+ "gix-hash",
+ "gix-ignore",
+ "gix-index",
+ "gix-object",
+ "gix-path",
+ "gix-validate",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
+
+[[package]]
+name = "globset"
+version = "0.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3"
+dependencies = [
+ "aho-corasick",
+ "bstr",
+ "log",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "group"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
+dependencies = [
+ "ff",
+ "rand_core 0.6.4",
+ "subtle",
+]
+
+[[package]]
+name = "hash32"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
+dependencies = [
+ "byteorder",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.14.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+
+[[package]]
+name = "hashbrown"
+version = "0.15.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
+dependencies = [
+ "allocator-api2",
+ "equivalent",
+ "foldhash",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
+
+[[package]]
+name = "hashlink"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
+dependencies = [
+ "hashbrown 0.15.5",
+]
+
+[[package]]
+name = "heapless"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
+dependencies = [
+ "hash32",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "hkdf"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
+dependencies = [
+ "hmac",
+]
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
+[[package]]
+name = "home"
+version = "0.5.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d"
+dependencies = [
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "http-auth"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "150fa4a9462ef926824cf4519c84ed652ca8f4fbae34cb8af045b5cbcaf98822"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "log",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "icu_collections"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
+dependencies = [
+ "displaydoc",
+ "potential_utf",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locale_core"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
+dependencies = [
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
+
+[[package]]
+name = "icu_properties"
+version = "2.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec"
+dependencies = [
+ "icu_collections",
+ "icu_locale_core",
+ "icu_properties_data",
+ "icu_provider",
+ "zerotrie",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "2.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af"
+
+[[package]]
+name = "icu_provider"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
+dependencies = [
+ "displaydoc",
+ "icu_locale_core",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerotrie",
+ "zerovec",
+]
+
+[[package]]
+name = "idna"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
+dependencies = [
+ "idna_adapter",
+ "smallvec",
+ "utf8_iter",
+]
+
+[[package]]
+name = "idna_adapter"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
+dependencies = [
+ "icu_normalizer",
+ "icu_properties",
+]
+
+[[package]]
+name = "ignore"
+version = "0.4.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a"
+dependencies = [
+ "crossbeam-deque",
+ "globset",
+ "log",
+ "memchr",
+ "regex-automata",
+ "same-file",
+ "walkdir",
+ "winapi-util",
+]
+
+[[package]]
+name = "im-rc"
+version = "15.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe"
+dependencies = [
+ "bitmaps",
+ "rand_core 0.6.4",
+ "rand_xoshiro",
+ "sized-chunks",
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "imara-diff"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17d34b7d42178945f775e84bc4c36dde7c1c6cdfea656d3354d009056f2bb3d2"
+dependencies = [
+ "hashbrown 0.15.5",
+]
+
+[[package]]
+name = "indexmap"
+version = "2.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.16.1",
+]
+
+[[package]]
+name = "is_executable"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baabb8b4867b26294d818bf3f651a454b6901431711abb96e296245888d6e8c4"
+dependencies = [
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
+
+[[package]]
+name = "itertools"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itertools"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
+
+[[package]]
+name = "jiff"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35"
+dependencies = [
+ "jiff-static",
+ "jiff-tzdb-platform",
+ "log",
+ "portable-atomic",
+ "portable-atomic-util",
+ "serde_core",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "jiff-static"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "jiff-tzdb"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68971ebff725b9e2ca27a601c5eb38a4c5d64422c4cbab0c535f248087eda5c2"
+
+[[package]]
+name = "jiff-tzdb-platform"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8"
+dependencies = [
+ "jiff-tzdb",
+]
+
+[[package]]
+name = "jobserver"
+version = "0.1.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
+dependencies = [
+ "getrandom 0.3.4",
+ "libc",
+]
+
+[[package]]
+name = "js-sys"
+version = "0.3.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "kstring"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1"
+dependencies = [
+ "static_assertions",
+]
+
+[[package]]
+name = "lazy-regex"
+version = "3.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "191898e17ddee19e60bccb3945aa02339e81edd4a8c50e21fd4d48cdecda7b29"
+dependencies = [
+ "lazy-regex-proc_macros",
+ "once_cell",
+ "regex",
+]
+
+[[package]]
+name = "lazy-regex-proc_macros"
+version = "3.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c35dc8b0da83d1a9507e12122c80dea71a9c7c613014347392483a83ea593e04"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "regex",
+ "syn",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "lazycell"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
+
+[[package]]
+name = "libc"
+version = "0.2.178"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
+
+[[package]]
+name = "libgit2-sys"
+version = "0.18.3+1.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9b3acc4b91781bb0b3386669d325163746af5f6e4f73e6d2d630e09a35f3487"
+dependencies = [
+ "cc",
+ "libc",
+ "libssh2-sys",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+]
+
+[[package]]
+name = "libloading"
+version = "0.8.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
+dependencies = [
+ "cfg-if",
+ "windows-link",
+]
+
+[[package]]
+name = "libnghttp2-sys"
+version = "0.1.11+1.64.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b6c24e48a7167cffa7119da39d577fa482e66c688a4aac016bee862e1a713c4"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "libredox"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50"
+dependencies = [
+ "bitflags",
+ "libc",
+ "redox_syscall 0.6.0",
+]
+
+[[package]]
+name = "libsqlite3-sys"
+version = "0.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91632f3b4fb6bd1d72aa3d78f41ffecfcf2b1a6648d8c241dbe7dbfaf4875e15"
+dependencies = [
+ "cc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "libssh2-sys"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "220e4f05ad4a218192533b300327f5150e809b54c4ec83b5a1d91833601811b9"
+dependencies = [
+ "cc",
+ "libc",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "libz-rs-sys"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15413ef615ad868d4d65dce091cb233b229419c7c0c4bcaa746c0901c49ff39c"
+dependencies = [
+ "zlib-rs",
+]
+
+[[package]]
+name = "libz-sys"
+version = "1.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
+
+[[package]]
+name = "litemap"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
+
+[[package]]
+name = "lock_api"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
+
+[[package]]
+name = "matchers"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
+dependencies = [
+ "regex-automata",
+]
+
+[[package]]
+name = "maybe-async"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
+
+[[package]]
+name = "memmap2"
+version = "0.9.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.8.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
+dependencies = [
+ "adler2",
+ "simd-adler32",
+]
+
+[[package]]
+name = "miow"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "536bfad37a309d62069485248eeaba1e8d9853aaf951caaeaed0585a95346f08"
+dependencies = [
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "nix"
+version = "0.30.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "cfg_aliases",
+ "libc",
+]
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "normpath"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf23ab2b905654b4cb177e30b629937b3868311d4e1cba859f899c041046e69b"
+dependencies = [
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "nu-ansi-term"
+version = "0.50.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
+dependencies = [
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
+dependencies = [
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
+[[package]]
+name = "num-integer"
+version = "0.1.46"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "objc2"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05"
+dependencies = [
+ "objc2-encode",
+]
+
+[[package]]
+name = "objc2-cloud-kit"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
+dependencies = [
+ "bitflags",
+ "objc2",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "objc2-core-data"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
+dependencies = [
+ "objc2",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "objc2-core-foundation"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
+dependencies = [
+ "bitflags",
+ "dispatch2",
+ "objc2",
+]
+
+[[package]]
+name = "objc2-core-graphics"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
+dependencies = [
+ "bitflags",
+ "dispatch2",
+ "objc2",
+ "objc2-core-foundation",
+ "objc2-io-surface",
+]
+
+[[package]]
+name = "objc2-core-image"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006"
+dependencies = [
+ "objc2",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "objc2-core-location"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009"
+dependencies = [
+ "objc2",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "objc2-core-text"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
+dependencies = [
+ "bitflags",
+ "objc2",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
+]
+
+[[package]]
+name = "objc2-encode"
+version = "4.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
+
+[[package]]
+name = "objc2-foundation"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
+dependencies = [
+ "bitflags",
+ "block2",
+ "libc",
+ "objc2",
+ "objc2-core-foundation",
+]
+
+[[package]]
+name = "objc2-io-surface"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
+dependencies = [
+ "bitflags",
+ "objc2",
+ "objc2-core-foundation",
+]
+
+[[package]]
+name = "objc2-quartz-core"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
+dependencies = [
+ "bitflags",
+ "objc2",
+ "objc2-core-foundation",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "objc2-ui-kit"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
+dependencies = [
+ "bitflags",
+ "block2",
+ "objc2",
+ "objc2-cloud-kit",
+ "objc2-core-data",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
+ "objc2-core-image",
+ "objc2-core-location",
+ "objc2-core-text",
+ "objc2-foundation",
+ "objc2-quartz-core",
+ "objc2-user-notifications",
+]
+
+[[package]]
+name = "objc2-user-notifications"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e"
+dependencies = [
+ "objc2",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
+name = "once_cell_polyfill"
+version = "1.70.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
+
+[[package]]
+name = "opener"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb9024962ab91e00c89d2a14352a8d0fc1a64346bf96f1839b45c09149564e47"
+dependencies = [
+ "bstr",
+ "normpath",
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.111"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "ordered-float"
+version = "2.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "orion"
+version = "0.17.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21b3da83b2b4cdc74ab6a556b2e7b473da046d5aa4008c0a7a3ae96b1b4aabb4"
+dependencies = [
+ "fiat-crypto",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "os_info"
+version = "3.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224"
+dependencies = [
+ "android_system_properties",
+ "log",
+ "nix",
+ "objc2",
+ "objc2-foundation",
+ "objc2-ui-kit",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "p384"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6"
+dependencies = [
+ "ecdsa",
+ "elliptic-curve",
+ "primeorder",
+ "sha2",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall 0.5.18",
+ "smallvec",
+ "windows-link",
+]
+
+[[package]]
+name = "pasetors"
+version = "0.7.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03e1ed71dcdf863d9f66d9de86de714db38aedc2fcabc1a60207d1fde603e2d5"
+dependencies = [
+ "ct-codecs",
+ "ed25519-compact",
+ "getrandom 0.3.4",
+ "orion",
+ "p384",
+ "rand_core 0.6.4",
+ "regex",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "sha2",
+ "subtle",
+ "time",
+ "zeroize",
+]
+
+[[package]]
+name = "pathdiff"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
+
+[[package]]
+name = "pem-rfc7468"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
+dependencies = [
+ "base64ct",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
+
+[[package]]
+name = "pkcs8"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
+dependencies = [
+ "der",
+ "spki",
+]
+
+[[package]]
+name = "pkg-config"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+
+[[package]]
+name = "portable-atomic"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
+
+[[package]]
+name = "portable-atomic-util"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
+dependencies = [
+ "portable-atomic",
+]
+
+[[package]]
+name = "potential_utf"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
+dependencies = [
+ "zerovec",
+]
+
+[[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "primeorder"
+version = "0.13.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
+dependencies = [
+ "elliptic-curve",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.103"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "prodash"
+version = "30.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a6efc566849d3d9d737c5cb06cc50e48950ebe3d3f9d70631490fff3a07b139"
+dependencies = [
+ "parking_lot",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r-efi"
+version = "5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
+[[package]]
+name = "rand"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
+dependencies = [
+ "rand_chacha",
+ "rand_core 0.9.3",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.9.3",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom 0.2.16",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
+dependencies = [
+ "getrandom 0.3.4",
+]
+
+[[package]]
+name = "rand_xoshiro"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
+dependencies = [
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec96166dafa0886eb81fe1c0a388bece180fbef2135f97c1e2cf8302e74b43b5"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "regex"
+version = "1.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
+
+[[package]]
+name = "rfc6979"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
+dependencies = [
+ "hmac",
+ "subtle",
+]
+
+[[package]]
+name = "roff"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3"
+
+[[package]]
+name = "rowan"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "417a3a9f582e349834051b8a10c8d71ca88da4211e4093528e36b9845f6b5f21"
+dependencies = [
+ "countme",
+ "hashbrown 0.14.5",
+ "rustc-hash 1.1.0",
+ "text-size",
+]
+
+[[package]]
+name = "rusqlite"
+version = "0.36.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3de23c3319433716cf134eed225fe9986bc24f63bed9be9f20c329029e672dc7"
+dependencies = [
+ "bitflags",
+ "fallible-iterator",
+ "fallible-streaming-iterator",
+ "hashlink",
+ "libsqlite3-sys",
+ "smallvec",
+]
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "rustc-hash"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
+
+[[package]]
+name = "rustc-stable-hash"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "781442f29170c5c93b7185ad559492601acdc71d5bb0706f5868094f45cfcd08"
+
+[[package]]
+name = "rustfix"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "864792a841a1d785ba91b8d2a75e1936b40bc517020c3c2958ac403b92e4f00a"
+dependencies = [
+ "serde",
+ "serde_json",
+ "thiserror",
+ "tracing",
+]
+
+[[package]]
+name = "rustix"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "ryu"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "schannel"
+version = "0.1.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1"
+dependencies = [
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "sec1"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
+dependencies = [
+ "base16ct",
+ "der",
+ "generic-array",
+ "pkcs8",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "security-framework"
+version = "3.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef"
+dependencies = [
+ "bitflags",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+dependencies = [
+ "serde_core",
+ "serde_derive",
+]
+
+[[package]]
+name = "serde-untagged"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058"
+dependencies = [
+ "erased-serde",
+ "serde",
+ "serde_core",
+ "typeid",
+]
+
+[[package]]
+name = "serde-value"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
+dependencies = [
+ "ordered-float",
+ "serde",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_ignored"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "115dffd5f3853e06e746965a20dcbae6ee747ae30b543d91b0e089668bb07798"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.145"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
+dependencies = [
+ "itoa",
+ "memchr",
+ "ryu",
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "sha1"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sha1-checked"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89f599ac0c323ebb1c6082821a54962b839832b03984598375bff3975b804423"
+dependencies = [
+ "digest",
+ "sha1",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sharded-slab"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "shell-escape"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
+
+[[package]]
+name = "shell-words"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77"
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "signature"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
+dependencies = [
+ "digest",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "simd-adler32"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
+
+[[package]]
+name = "sized-chunks"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e"
+dependencies = [
+ "bitmaps",
+ "typenum",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+
+[[package]]
+name = "smawk"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
+
+[[package]]
+name = "socket2"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"
+dependencies = [
+ "libc",
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "spki"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
+dependencies = [
+ "base64ct",
+ "der",
+]
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "subtle"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+
+[[package]]
+name = "supports-hyperlinks"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e396b6523b11ccb83120b115a0b7366de372751aa6edf19844dfb13a6af97e91"
+
+[[package]]
+name = "supports-unicode"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2"
+
+[[package]]
+name = "syn"
+version = "2.0.111"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tar"
+version = "0.4.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a"
+dependencies = [
+ "filetime",
+ "libc",
+ "xattr",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
+dependencies = [
+ "fastrand",
+ "getrandom 0.3.4",
+ "once_cell",
+ "rustix",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "terminal_size"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0"
+dependencies = [
+ "rustix",
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "text-size"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233"
+
+[[package]]
+name = "textwrap"
+version = "0.16.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
+dependencies = [
+ "smawk",
+ "unicode-linebreak",
+ "unicode-width",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "time"
+version = "0.3.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
+dependencies = [
+ "deranged",
+ "itoa",
+ "num-conv",
+ "powerfmt",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
+
+[[package]]
+name = "time-macros"
+version = "0.2.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
+dependencies = [
+ "num-conv",
+ "time-core",
+]
+
+[[package]]
+name = "tinystr"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
+dependencies = [
+ "displaydoc",
+ "zerovec",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "toml"
+version = "0.8.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
+dependencies = [
+ "serde",
+ "serde_spanned 0.6.9",
+ "toml_datetime 0.6.11",
+ "toml_edit 0.22.27",
+]
+
+[[package]]
+name = "toml"
+version = "0.9.9+spec-1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb5238e643fc34a1d5d7e753e1532a91912d74b63b92b3ea51fde8d1b7bc79dd"
+dependencies = [
+ "indexmap",
+ "serde_core",
+ "serde_spanned 1.0.4",
+ "toml_datetime 0.7.4+spec-1.0.0",
+ "toml_parser",
+ "toml_writer",
+ "winnow",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.7.4+spec-1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe3cea6b2aa3b910092f6abd4053ea464fab5f9c170ba5e9a6aead16ec4af2b6"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned 0.6.9",
+ "toml_datetime 0.6.11",
+ "toml_write",
+ "winnow",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.23.10+spec-1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269"
+dependencies = [
+ "indexmap",
+ "serde_core",
+ "serde_spanned 1.0.4",
+ "toml_datetime 0.7.4+spec-1.0.0",
+ "toml_parser",
+ "toml_writer",
+ "winnow",
+]
+
+[[package]]
+name = "toml_parser"
+version = "1.0.5+spec-1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c03bee5ce3696f31250db0bbaff18bc43301ce0e8db2ed1f07cbb2acf89984c"
+dependencies = [
+ "winnow",
+]
+
+[[package]]
+name = "toml_write"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
+
+[[package]]
+name = "toml_writer"
+version = "1.0.5+spec-1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9cd6190959dce0994aa8970cd32ab116d1851ead27e866039acaf2524ce44fa"
+
+[[package]]
+name = "tracing"
+version = "0.1.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647"
+dependencies = [
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tracing-chrome"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf0a738ed5d6450a9fb96e86a23ad808de2b727fd1394585da5cdd6788ffe724"
+dependencies = [
+ "serde_json",
+ "tracing-core",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c"
+dependencies = [
+ "once_cell",
+ "valuable",
+]
+
+[[package]]
+name = "tracing-log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
+dependencies = [
+ "log",
+ "once_cell",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
+dependencies = [
+ "matchers",
+ "nu-ansi-term",
+ "once_cell",
+ "regex-automata",
+ "sharded-slab",
+ "smallvec",
+ "thread_local",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
+]
+
+[[package]]
+name = "typeid"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
+
+[[package]]
+name = "typenum"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
+
+[[package]]
+name = "unicase"
+version = "2.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
+
+[[package]]
+name = "unicode-bom"
+version = "2.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
+
+[[package]]
+name = "unicode-linebreak"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-width"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+
+[[package]]
+name = "url"
+version = "2.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+ "serde",
+]
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "valuable"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
+
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
+[[package]]
+name = "wasip2"
+version = "1.0.1+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
+dependencies = [
+ "wit-bindgen",
+]
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40"
+dependencies = [
+ "bumpalo",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "winapi-util"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
+dependencies = [
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.62.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-link",
+ "windows-result",
+ "windows-strings",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.59.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-link"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
+
+[[package]]
+name = "windows-result"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
+dependencies = [
+ "windows-targets 0.53.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.61.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
+ "windows_i686_gnullvm 0.52.6",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.53.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
+dependencies = [
+ "windows-link",
+ "windows_aarch64_gnullvm 0.53.1",
+ "windows_aarch64_msvc 0.53.1",
+ "windows_i686_gnu 0.53.1",
+ "windows_i686_gnullvm 0.53.1",
+ "windows_i686_msvc 0.53.1",
+ "windows_x86_64_gnu 0.53.1",
+ "windows_x86_64_gnullvm 0.53.1",
+ "windows_x86_64_msvc 0.53.1",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
+
+[[package]]
+name = "winnow"
+version = "0.7.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
+
+[[package]]
+name = "writeable"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
+
+[[package]]
+name = "xattr"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156"
+dependencies = [
+ "libc",
+ "rustix",
+]
+
+[[package]]
+name = "yoke"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
+dependencies = [
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.8.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zeroize"
+version = "1.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
+
+[[package]]
+name = "zerotrie"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+]
+
+[[package]]
+name = "zerovec"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "zlib-rs"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51f936044d677be1a1168fae1d03b583a285a5dd9d8cbf7b24c23aa1fc775235"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644 (file)
index 0000000..ed534c3
--- /dev/null
@@ -0,0 +1,167 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+rust-version = "1.58"
+name = "debcargo"
+version = "2.8.1"
+authors = [
+    "Josh Triplett <josh@joshtriplett.org>",
+    "Ximin Luo <infinity0@debian.org>",
+    "Vasudev Kamath <vasudev@copyninja.info>",
+    "Fabian Grünbichler <debian@fabian.gruenbichler.email>",
+]
+build = false
+autolib = false
+autobins = false
+autoexamples = false
+autotests = false
+autobenches = false
+description = "Create a Debian package from a Cargo crate."
+readme = "README.md"
+license = "MIT/Apache-2.0"
+repository = "https://salsa.debian.org/rust-team/debcargo"
+
+[features]
+default = ["update-dependencies"]
+update-dependencies = ["debian-control"]
+
+[lib]
+name = "debcargo"
+path = "src/lib.rs"
+
+[[bin]]
+name = "debcargo"
+path = "src/bin/debcargo.rs"
+
+[[test]]
+name = "config_tests"
+path = "tests/config_tests.rs"
+
+[[test]]
+name = "local-crate"
+path = "tests/local-crate.rs"
+
+[[test]]
+name = "manpages"
+path = "tests/manpages.rs"
+
+[dependencies.anyhow]
+version = "1.0"
+
+[dependencies.cargo]
+version = "0.91"
+
+[dependencies.cargo-util]
+version = "0.2.14"
+
+[dependencies.cargo-util-schemas]
+version = "0.10"
+
+[dependencies.chrono]
+version = "0.4.31"
+
+[dependencies.clap]
+version = "4.5"
+features = [
+    "cargo",
+    "derive",
+    "wrap_help",
+]
+
+[dependencies.clap_mangen]
+version = "0.2.29"
+
+[dependencies.debian-control]
+version = "0.2.14"
+features = ["lossless"]
+optional = true
+default-features = false
+
+[dependencies.env_logger]
+version = "0.11"
+
+[dependencies.filetime]
+version = "0.2"
+
+[dependencies.flate2]
+version = "1"
+
+[dependencies.git2]
+version = ">= 0.19, < 0.21"
+
+[dependencies.glob]
+version = "0.3"
+
+[dependencies.itertools]
+version = ">= 0.13, <0.15"
+
+[dependencies.log]
+version = "0.4"
+
+[dependencies.nu-ansi-term]
+version = "0.50"
+
+[dependencies.regex]
+version = "1.0"
+
+[dependencies.semver]
+version = "1"
+
+[dependencies.serde]
+version = "1"
+
+[dependencies.serde_derive]
+version = "1"
+
+[dependencies.tar]
+version = "0.4"
+
+[dependencies.tempfile]
+version = "3"
+
+[dependencies.textwrap]
+version = "0.16"
+
+[dependencies.toml]
+version = "0.8"
+
+[dependencies.walkdir]
+version = "2"
+
+[lints.clippy]
+cast_possible_wrap = "warn"
+cloned_instead_of_copied = "warn"
+default_trait_access = "warn"
+doc_markdown = "warn"
+enum_glob_use = "warn"
+explicit_deref_methods = "warn"
+explicit_into_iter_loop = "warn"
+explicit_iter_loop = "warn"
+flat_map_option = "warn"
+if_not_else = "warn"
+inefficient_to_string = "warn"
+items_after_statements = "warn"
+manual_string_new = "warn"
+map_unwrap_or = "warn"
+needless_pass_by_value = "warn"
+redundant_closure_for_method_calls = "warn"
+redundant_else = "warn"
+ref_option = "warn"
+ref_option_ref = "warn"
+semicolon_if_nothing_returned = "warn"
+single_char_pattern = "warn"
+single_match_else = "warn"
+uninlined_format_args = "warn"
+unnecessary_semicolon = "warn"
+unnested_or_patterns = "warn"
+wildcard_imports = "warn"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644 (file)
index 0000000..943a7c5
--- /dev/null
@@ -0,0 +1,73 @@
+[package]
+name = "debcargo"
+version = "2.8.1"
+authors = [
+ "Josh Triplett <josh@joshtriplett.org>",
+ "Ximin Luo <infinity0@debian.org>",
+ "Vasudev Kamath <vasudev@copyninja.info>",
+ "Fabian Grünbichler <debian@fabian.gruenbichler.email>",
+]
+license = "MIT/Apache-2.0"
+repository = "https://salsa.debian.org/rust-team/debcargo"
+description = "Create a Debian package from a Cargo crate."
+edition = "2021"
+rust-version = "1.58"
+
+[dependencies]
+anyhow = "1.0"
+cargo = "0.91"
+cargo-util = "0.2.14"
+cargo-util-schemas = "0.10"
+clap = { version = "4.5", features = ["cargo", "derive", "wrap_help"] }
+clap_mangen = { version = "0.2.29" }
+chrono = "0.4.31"
+env_logger = "0.11"
+filetime = "0.2"
+flate2 = "1"
+git2 = ">= 0.19, < 0.21"
+glob = "0.3"
+itertools = ">= 0.13, <0.15"
+log = "0.4"
+nu-ansi-term = "0.50"
+regex = "1.0"
+semver = "1"
+serde = "1"
+serde_derive = "1"
+tar = "0.4"
+textwrap = "0.16"
+tempfile = "3"
+toml = "0.8"
+walkdir = "2"
+debian-control = { version = "0.2.14", optional = true, default-features = false, features = ["lossless"] }
+
+[features]
+default = ["update-dependencies"]
+update-dependencies = ["debian-control"]
+
+[lints.clippy]
+uninlined_format_args = "warn"
+semicolon_if_nothing_returned = "warn"
+unnecessary_semicolon = "warn"
+redundant_closure_for_method_calls = "warn"
+explicit_iter_loop = "warn"
+items_after_statements = "warn"
+if_not_else = "warn"
+manual_string_new = "warn"
+wildcard_imports = "warn"
+flat_map_option = "warn"
+enum_glob_use = "warn"
+needless_pass_by_value = "warn"
+ref_option = "warn"
+ref_option_ref = "warn"
+single_char_pattern = "warn"
+default_trait_access = "warn"
+explicit_into_iter_loop = "warn"
+inefficient_to_string = "warn"
+single_match_else = "warn"
+map_unwrap_or = "warn"
+unnested_or_patterns = "warn"
+redundant_else = "warn"
+doc_markdown = "warn"
+explicit_deref_methods = "warn"
+cloned_instead_of_copied = "warn"
+cast_possible_wrap = "warn"
diff --git a/HACKING.md b/HACKING.md
new file mode 100644 (file)
index 0000000..10ab86d
--- /dev/null
@@ -0,0 +1,89 @@
+This file contains information about developing debcargo itself.
+
+
+## Dependencies
+
+For testing:
+
+```shell
+# Install dependencies for building (see README.md), then:
+$ apt-get install dh-cargo lintian
+```
+
+For development:
+
+```shell
+# As above, then:
+$ cargo install cargo-outdated
+$ cargo outdated -R
+```
+
+
+## Testing
+
+Whenever you make a major change, you should run:
+
+```shell
+$ tests/sh/integrate.sh -kbr debcargo exa fd-find ripgrep
+```
+
+in order to test it over a few hundred crates. Fix any build errors and
+important lintian errors that crop up.
+
+If you make a change that has wide-reaching implications, such as messing with
+the dependency logic, do a more thorough test:
+
+```shell
+$ tests/sh/integrate.sh -kbR debcargo exa fd-find ripgrep mdbook sccache
+```
+
+This will run the test over around a thousand crates. -R runs it over all the
+transitive dependencies of all the binary packages, which is needed for entry
+into Debian Testing. This is wider than -r, which runs the test over all the
+transitive build-dependencies of the source package, which is needed for entry
+into Debian Unstable.
+
+### Details
+
+To test the `debcargo` produced packages, you can run the following script.
+
+```shell
+$ tests/sh/integrate.sh crate[s]
+```
+
+where you can provide a list of crate names or local directories containing
+crates, and the script will run debcargo to create a source package (`.dsc`)
+and run lintian over it. If you find any issues, please add to the bugs in
+TODO.md file.
+
+```shell
+$ tests/sh/integrate.sh -kb crate[s]
+```
+
+will additionally run [sbuild](https://wiki.debian.org/sbuild) on the source
+package to build binary Debian packages (`.deb`) and run lintian over that too.
+It will automatically pick up any extra .debs you already have in the output
+directory, if they are dependencies of what you're building. The `-k` flag
+tells the script not to wipe the directory before it does anything else.
+
+```shell
+$ tests/sh/integrate.sh -kbr crate[s]
+```
+
+will run the script recursively over the listed crate(s) and all the transitive
+build-dependencies of the generated source packages, in dependency order. This
+covers all the dependencies that are needed for entry into Debian Unstable, and
+typically covers a few hundred crates. You may want or need to edit or update
+some of the overrides in `tests/configs`, to prune old or buggy dependencies.
+
+```shell
+$ tests/sh/integrate.sh -kbR crate[s]
+```
+
+will run the script recursively over the listed crate(s) and all the transitive
+runtime-dependencies of the binary packages, in dependency order. This covers
+all the dependencies that are needed for entry into Debian Testing, and
+typically covers a few thousand crates. You may want or need to edit or update
+some of the overrides in `tests/configs`, to prune old or buggy dependencies.
+
+See `-h` for other options.
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..6c197de
--- /dev/null
+++ b/README.md
@@ -0,0 +1,110 @@
+Rust crates to Debian packages
+==============================
+
+`debcargo` is the official tool for packaging Rust crates to be part of the
+[Debian](https://www.debian.org/) system.
+
+It creates a Debian source package (`*.dsc`) from a Rust crate that follows
+Debian's [general packaging policy](https://www.debian.org/doc/debian-policy/)
+as well as the Debian Rust team's [crate packaging
+policy](https://wiki.debian.org/Teams/RustPackaging/Policy).
+
+
+## Features ##
+
+ * Easy to customize, using config files and overlay directories. This includes
+   patching or otherwise fixing Rust crates to adhere to Debian policy.
+ * Guess copyright information from crate metadata and source code, used to
+   suggest appropriate values for `debian/copyright`.
+ * Put `FIXME (hint)` strings where it can't detect full information, so user
+   can provide an override/overlay or manually fix it.
+ * Resulting packages automatically support general functionality available to
+   all policy-conforming Debian packages, such as:
+   * binaries for [10+ architectures](https://www.debian.org/ports/) are made
+     available directly to users, via `apt-get`
+   * debugging symbols are placed in a separate binary package, integrating
+     with the standard Debian [distribution system for debugging
+     symbols](https://wiki.debian.org/HowToGetABacktrace)
+   * full system integration with non-Rust software, including cross-language
+     dependency resolution
+   * cross-compilation support, including automatic resolution and installation
+     of non-Rust cross-dependencies, via Debian build tools such as `sbuild`.
+ * Determine a crate's full dependency tree (i.e. build order), from both
+   Debian packaging and QA perspectives.
+
+
+## Installation
+
+On Debian systems, `debcargo` can be installed the usual way:
+
+```shell
+$ apt-get install debcargo
+```
+
+To build locally for development:
+
+```shell
+$ apt-get build-dep debcargo
+$ cargo build debcargo
+```
+
+On non-Debian systems, you can try simply:
+
+```shell
+$ cargo build debcargo
+```
+
+and fix any build errors that come up, e.g. by installing missing libraries.
+Probably, this will include OpenSSL as a dependency of cargo.
+
+
+## Examples ##
+
+To download and unpack the latest `clap` crate and prepare the source package:
+
+```shell
+$ debcargo package clap
+```
+
+To download and unpack version `2.25.0` of `clap` crate and prepare the source package:
+
+```shell
+$ debcargo package clap =2.25.0
+```
+
+To provide additional packaging-specific config for downloading and packaging
+latest `clap` crate from crates.io:
+
+```shell
+$ debcargo package --config clap-2/debian/debcargo.toml clap
+```
+
+See `debcargo.toml.example` for a sample TOML file.
+
+
+## Long-term package maintenance
+
+The Debian Rust team uses this tool together with the configs and overlays in
+https://salsa.debian.org/rust-team/debcargo-conf/. If you are interested in
+contributing, please see that repository for further information and
+instructions on how to collaborate with us.
+
+
+## Building unofficial Debian packages
+
+Debian packaging policy is quite detailed. If you just want to create Debian
+binary packages (`*.deb`) without worrying about these policies, you may want
+to use other tools instead that ignore and bypass these policies. For example,
+`cargo-deb`.
+
+The trade-off is that the resulting packages integrate less well with a Debian
+system, and do not integrate at all with the Debian build system, which means
+you lose the features described earlier. Furthermore, you will be responsible
+for hosting and distributing those packages yourself, outside of the official
+Debian distribution infrastructure.
+
+
+## License ##
+
+Debcargo is licensed under `MIT/Apache-2.0`. It is written by `Josh Triplett`
+and `Ximin Luo`, and improved by members of **Debian Rust Maintainers team**
diff --git a/TODO.md b/TODO.md
new file mode 100644 (file)
index 0000000..3d9e017
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,26 @@
+See https://salsa.debian.org/groups/rust-team/-/issues
+
+See HACKING.md for development and testing instructions.
+
+## Lower-priority tasks
+
+Minor issues
+
+- fs::rename cannot handle cross-device moves, e.g. if --directory is on a
+  different partition from . then debcargo fails
+
+- the ? syntax loses the stack, use Result.expect() to give context, or use
+  error-chain instead...
+
+- [ ] globset, ignore, termcolor:
+      When generating d/copyright, failed to clone repository
+      https://github.com/BurntSushi/ripgrep/tree/master/XXX: unexpected HTTP status code: 404; class=Net (12)
+
+Features for later
+
+- [ ] Integrate `apt-pkg-native` crate to check if the crate or its dependency
+      is already in archive and display information.
+- [ ] Display first level dependency with equivalent Debian names at the end
+      which are not yet packaged in Debian as a information to maintainer.
+- [ ] Employ `licensecheck` tool to look for license and copyright information.
+      Currently we use regex to grep through sources.
diff --git a/debcargo.toml.example b/debcargo.toml.example
new file mode 100644 (file)
index 0000000..bdf8ac0
--- /dev/null
@@ -0,0 +1,278 @@
+# Whether to generate a package for the binary crate. If omitted, defaults to
+# true unless semver_suffix (see below) is also true.
+#bin = true
+
+# Name for the binary crate. Defaults to "<default>" which means the crate
+# name, with no "rust-" prefix and with underscores replaced by hyphens.
+#bin_name = "<default>"
+
+# Add the semver to the package name, to allow co-installation with other
+# versions of the same crate. This should only be true for crates older than
+# the most up-to-date version in Debian, and only if they are needed as a
+# (direct or indirect) build dependency of another binary crate.
+#
+# If you set this to true, you should either omit "bin" or set it to false,
+# unless you are sure the old and new packages are co-installable.
+#semver_suffix = false
+
+# Overlay directory to copy on top of the generated one, given relative to the
+# directory that contains this config file. If any files conflict with the ones
+# generated by debcargo, the latter are moved to <file>.debcargo.hint instead.
+#
+# For the special case of debian/changelog, generated entries will be prepended
+# to the top of the existing d/changelog (from the overlay), rather than stored
+# in debian/changelog.debcargo.hint. A further exception: if the distribution
+# of the top entry in the existing d/changelog is
+# UNRELEASED-FIXME-AUTOGENERATED-DEBCARGO then that whole entry will be
+# *replaced* with the generated entry, not prepended.
+#
+# Normally, any "hints" generated are written back to the overlay directory,
+# overwriting any hints that may have previously been stored there. For the
+# special case of debian/changelog, that is written-back as-is. Therefore, it
+# is strongly recommended that you keep the overlay directory tracked in
+# version control. To disable this behaviour, give --no-overlay-write-back on
+# the debcargo command line.
+#
+#overlay = "."
+
+# Local directory where crate can be found, instead of crates.io. Resolved
+# relative to the directory that contains this config file. Note: this is
+# currently experimental and only works for crates whose dependencies are all
+# published on crates.io. For example, not rustup. This limitation will
+# hopefully be fixed in the future.
+#
+#crate_src_path = "../.."
+
+# Paths from the crate tarball, to exclude from the orig tarball.
+# See https://docs.rs/glob/latest/glob/struct.Pattern.html for syntax
+#excludes = ["libgit2/**"]
+
+# Paths from the crate tarball, that have been manually reviewed to adhere to
+# Debian policy. debcargo has a crude method for detecting files that might not
+# fit within policy, and will give a fatal error if any are detected. In the
+# exceptional cases where the method gives a false-positive, add them here.
+#whitelist = ["libgit2/**"]
+
+# Whether to allow prerelease deps, by rewriting these to the released version.
+# This should only be enabled for certain crates if really necessary, and first
+# you should check that they can actually build when this is enabled.
+#allow_prerelease_deps = false
+
+# This is the stem of the short description for each binary package. By default
+# `debcargo` will try to auto-extract a description from `Cargo.toml` but
+# sometimes this may lead to a meaningless, weird short description.
+#
+# The full short description of each binary package is constructed using this
+# string plus an auto-generated suffix. The full string can be overridden by
+# the [packages.KEY].summary config key, see below.
+#summary = "PLACEHOLDER"
+
+# This is the stem of the long description for each binary package. By default
+# this is empty.
+#
+# The full long description of each binary package is constructed using this
+# string plus an auto-generated suffix. The full string can be overridden by
+# the [packages.KEY].description config key, see below.
+#description = """
+#PLACEHOLDER
+#"""
+
+# Maintainer
+#
+# Defaults to pkg-rust-team, should only be overriden with care. If overridden,
+# vcs_* in [source] should also be overridden, otherwise they point the Rust
+# Team's salsa project.
+#
+#maintainer = "PLACEHOLDER"
+
+# Uploaders. This affects the Uploaders: field in debian/control as well as the
+# additional maintainers listed in debian/copyright. The naming is historical;
+# in Debian today for team-maintained packages, this is generally taken to mean
+# "the main individuals" responsible for the package - anyone on the team is
+# "morally allowed" to perform the upload as long as they specify "Team upload"
+# in debian/changelog; this is done automatically by debcargo.
+uploaders = [ "foo bar <foo@debian.org>" ]
+
+# This is a temporary work-around in order to address situations where certain
+# Debian infrastructure people claim (without supplying concrete evidence) that
+# rust crate metadata is "too large". This flag addresses this, effectively by
+# forcing all crate features together into a single feature. This increases the
+# dependency footprint of the generated packages and therefore should not be
+# enabled unless absolutely necessary. It can also cause cyclic dependencies in
+# some cases, and in these cases it simply cannot be enabled, as packages in
+# the cycle become uninstallable. Most crates should not need this, and you
+# should not enable this just because "somebody told you so".
+#collapse_features = false
+
+# Set the Rules-Requires-Root field in debian/control; by default, this unset.
+#requires_root = "yes"
+
+[source]
+
+# Debian Standards-Version to use. By default debcargo uses latest policy version.
+#policy = "4.0.0"
+
+# Override or provide missing homepage for crate
+#homepage = "https://clap.rs"
+
+# Override the VCS entries.
+# By default this points to a relevant subdirectory underneath the main
+# repository for debcargo config files, owned by the Debian Rust Maintainers:
+# https://salsa.debian.org/rust-team/debcargo-conf/
+# Please only override this if your package is truly special, e.g. it combines
+# lots of languages and/or there is not a crate at the top-level directory. In
+# most cases you should prefer packaging as part of the Debian Rust Team, see
+# https://wiki.debian.org/Teams/RustPackaging/Policy
+#
+#vcs_git = "https://salsa.debian.org/special_package/rust-special-0.1.git"
+#vcs_browser = "https://salsa.debian.org/special_package/rust-special-0.1"
+
+# Section override for the source package. Unless overridden here, library
+# crates get "rust" and non-library crates get a "FIXME".
+#section = "rust"
+
+# Extra Build-Depends on top of those generated by debcargo.
+# If you defined a custom d/rules that does extra stuff on top of dh-cargo,
+# then you may need to use this.
+#
+# OTOH, if your crate needs external development headers to build, these should
+# probably instead go in the [packages.lib] depends key rather than this key.
+# debcargo will then automatically add those into the package Build-Depends if
+# needed by dh-cargo; you don't have to add them here as well. Unless the extra
+# dependency is needed for the clean target of debian/rules, the _indep variant
+# is probably the right choice.
+#build_depends = ["PLACEHOLDER", "PLACEHOLDER"]
+#build_depends_arch = ["PLACEHOLDER", "PLACEHOLDER"]
+#build_depends_indep = ["PLACEHOLDER", "PLACEHOLDER"]
+
+# If set to `true`, do not add <!nocheck> annotations to build dependencies.
+# This should only be needed if your librust-* packages actually require some
+# build step, or your package does something else custom.
+#skip_nocheck = false
+
+# Build-Depends to subtract from those generated by debcargo. This should be
+# used when our default generated Build-Depends results in a cycle. For
+# example, this might happen if:
+#
+# - crate A's default-feature depends on crate B's no-default-features (which has no dependencies)
+# - crate B's default-feature depends on crate A's no-default-features (which has no dependencies)
+#
+# In these cases, you'll need to (for example) add "librustA+B-dev <!nocheck>"
+# to build_depends_excludes in A's debcargo.toml to break the cycle, and also
+# add override_dh_auto_test to A's d/rules to avoid selecting the B feature
+# when running the test build. Depending on the exact situation, it should be
+# sufficient to do this override only for one of the packages in the cycle.
+#
+# Note that binary package Depends must be left alone in order to correctly
+# express the dependencies; these ought not to have cycles in anyway, even in
+# a case like the above example.
+#
+# This field should *not* be used to exclude arch-specific dependencies. We
+# want to include them to support cross-compiling, and they should cause no
+# problems since they are just source code. If our test "cargo build" fails for
+# one of those dependencies, it should be handled in that package by disabling
+# the failing test on the architectures that they are expected to fail on. This
+# field applies to all three categories of build dependencies (Build-Depends,
+# Build-Depends-Arch and Build-Depends-Indep)
+#build_depends_excludes = ["PLACEHOLDER", "PLACEHOLDER"]
+
+# Binary package overrides.
+#
+# Different values for KEY selects different binary packages:
+# lib                 - the package for the library crate
+# "lib+FEATURE"       - the metapackage for feature FEATURE
+# bin                 - the package for the binary crate
+# "extra+PACKAGENAME" - extra package, e.g. for a cdylib
+#
+[packages.KEY]
+
+# Section override for the binary package. Use this if your crate is both a
+# library and a binary crate; in this case, omit source.section which will
+# default to "rust" and override this value for your binary package.
+#section = "PLACEHOLDER"
+
+# Short description for the package. If omitted, debcargo autogenerates this
+# using the top-level "summary" key plus a suffix describing the feature.
+#summary = "PLACEHOLDER"
+
+# Long description for the package. If omitted, debcargo autogenerates this
+# using the top-level "description" key plus a suffix describing the feature.
+#description = """
+#PLACEHOLDER
+#"""
+
+# Value for the Architecture field of the package. If omitted, debcargo will
+# set "any" for both 'bin' and 'lib' packages.
+# Note that 'lib' packages should not be "Architecture: all". For reference,
+# see https://rust-team.pages.debian.net/book/policy.html#why-architecture-any
+#architecture = ["PLACEHOLDER", "PLACEHOLDER"]
+
+# Value for the Multi-Arch field of the package. If omitted, debcargo will
+# automatically set 'foreign' for 'bin', and 'same' for all 'lib' packages.
+#multi_arch = "no|same|foreign|allowed"
+
+# Additional Depends on top of the ones generated by debcargo. This should be
+# used to pull in system libraries for crates that need them to build. You'll
+# want the -dev versions of the library packages, since our crate packages are
+# development packages and not runtime packages. These will be automatically
+# added to the source packages `Build-Depends-Arch` field as well.
+#depends = ["PLACEHOLDER", "PLACEHOLDER"]
+
+# We generate an autopkgtest (post-install test) for every feature, and also
+# run `cargo test` for the default feature set during build-time if there are
+# no additional dev-dependencies.
+#
+# However sometimes this may not work, e.g. if the crate is part of a larger
+# workspace and its tests require files from the workspace directory. Or if
+# the crate author is simply negligent and didn't ensure the test passes for
+# all features. In these cases, you can use this setting to mark the test as
+# "flaky" to ignore failures. Special cases for packages.KEY:
+#
+# packages."lib+@"      - disables the test for the --all-features autopkgtest
+#
+# The effect is transitive to its reverse-dependencies, so e.g. if you specify
+# this for feature A, and feature B depends on feature A, then feature B also
+# implicitly has this set. To unset it on feature B (and its transitive rdeps),
+# explicit set this to false for feature B as well.
+#
+# So for example if the test breaks for the bare library (when running with
+# --no-default-features) but works when the std feature is enabled, set this to
+# true for [packages.lib] and false for [packages."lib+std"].
+#
+# Note: debcargo will error if you set these in an inconsistent way. For
+# example if feature A depends on {B, C}, B says true and C says false, of
+# course we cannot determine what A should be. You can suppress the error by
+# explicitly giving A a value, either true or false.
+#
+#test_is_broken = false
+
+# Some tests depend on extra system tools or libraries, which need to be given
+# to autopkgtest. Like test_is_broken, the effect is transitive to its rdeps.
+#test_depends = []
+
+# Some tests might be broken on certain architectures, or just take too long.
+# This allows to (transitively) set Architecture restrictions (either positive
+# or negative) for autopkgtests. Use an explicit empty list ([]) to reset an
+# inherited restriction. The "@" (all features) test will default to a
+# combination of all individual restrictions.
+#test_architecture = []
+
+# Note: we do not (currently) support unsetting of this in indirect rdeps. This
+# would result in similar conflict issues as documented for test_is_broken. It
+# is possible to work around it similarly, by requiring manual resolution - but
+# cancelling dependencies is harder to implement than true/false so we avoid it
+# for now. Please file an issue if you have a real use-case for it.
+
+# More additional fields. This is mostly useful for binary packages that might
+# relate to other external programs, e.g. debcargo Recommends cargo.
+# The values here will extend those set by debcargo automatically.
+#recommends = ["PLACEHOLDER", "PLACEHOLDER"]
+#suggests = ["PLACEHOLDER", "PLACEHOLDER"]
+#provides = ["PLACEHOLDER", "PLACEHOLDER"]
+#breaks = ["PLACEHOLDER", "PLACEHOLDER"]
+#replaces = ["PLACEHOLDER", "PLACEHOLDER"]
+#conflicts = ["PLACEHOLDER", "PLACEHOLDER"]
+
+# Extra lines to include in the stanza, freeform. Use this to include things
+# that debcargo doesn't handle, such as Breaks, Conflicts, Replaces.
+#extra_lines = ["PLACEHOLDER", "PLACEHOLDER"]
diff --git a/manpages/debcargo-build-order.1 b/manpages/debcargo-build-order.1
new file mode 100644 (file)
index 0000000..7f9a4e7
--- /dev/null
@@ -0,0 +1,32 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo-build-order 1  "build-order " 
+.SH NAME
+debcargo\-build\-order \- Print the transitive dependencies of a package in topological order
+.SH SYNOPSIS
+\fBdebcargo build\-order\fR [\fB\-\-config\-dir\fR] [\fB\-\-resolve\-type\fR] [\fB\-\-emulate\-collapse\-features\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fICRATE_NAME\fR> [\fIVERSION\fR] 
+.SH DESCRIPTION
+Print the transitive dependencies of a package in topological order
+.SH OPTIONS
+.TP
+\fB\-\-config\-dir\fR \fI<CONFIG_DIR>\fR
+Directory for configs. The config subdirectory for a given crate is looked up by their crate name and version, from more specific to less specific, e.g. <crate>\-1.2.3, then <crate>\-1.2, then <crate>\-1 and finally <crate>. The config file is read from the debian/debcargo.toml subpath of the looked\-up subdirectory
+.TP
+\fB\-\-resolve\-type\fR \fI<RESOLVE_TYPE>\fR [default: SourceForDebianUnstable]
+Resolution type
+.br
+
+.br
+[\fIpossible values: \fRSourceForDebianUnstable, BinaryAllForDebianTesting]
+.TP
+\fB\-\-emulate\-collapse\-features\fR
+Emulate resolution as if every package were built with \-\-collapse\-features
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
+.TP
+<\fICRATE_NAME\fR>
+Name of the crate to package
+.TP
+[\fIVERSION\fR]
+Version of the crate to package; may contain dependency operators
diff --git a/manpages/debcargo-deb-dependencies.1 b/manpages/debcargo-deb-dependencies.1
new file mode 100644 (file)
index 0000000..db1f0f6
--- /dev/null
@@ -0,0 +1,31 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo-deb-dependencies 1  "deb-dependencies " 
+.SH NAME
+debcargo\-deb\-dependencies \- Print the dependencies of a package in d/control format
+.SH SYNOPSIS
+\fBdebcargo deb\-dependencies\fR [\fB\-\-features\fR] [\fB\-\-all\-features\fR] [\fB\-\-no\-default\-features\fR] [\fB\-\-allow\-prerelease\-deps\fR] [\fB\-\-include\-dev\-dependencies\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fICARGO_TOML\fR> 
+.SH DESCRIPTION
+Print the dependencies of a package in d/control format
+.SH OPTIONS
+.TP
+\fB\-\-features\fR \fI<FEATURES>\fR
+Features to include in dependencies
+.TP
+\fB\-\-all\-features\fR
+Include all features in dependencies
+.TP
+\fB\-\-no\-default\-features\fR
+Do not include default feature in dependencies
+.TP
+\fB\-\-allow\-prerelease\-deps\fR
+Allow prerelease versions of dependencies
+.TP
+\fB\-\-include\-dev\-dependencies\fR
+Include dev\-dependencies
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
+.TP
+<\fICARGO_TOML\fR>
+Cargo.toml for generating dependencies
diff --git a/manpages/debcargo-deb-src-name.1 b/manpages/debcargo-deb-src-name.1
new file mode 100644 (file)
index 0000000..7805af1
--- /dev/null
@@ -0,0 +1,19 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo-deb-src-name 1  "deb-src-name " 
+.SH NAME
+debcargo\-deb\-src\-name \- Print the Debian package name for a crate
+.SH SYNOPSIS
+\fBdebcargo deb\-src\-name\fR [\fB\-h\fR|\fB\-\-help\fR] <\fICRATE_NAME\fR> [\fIVERSION\fR] 
+.SH DESCRIPTION
+Print the Debian package name for a crate
+.SH OPTIONS
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
+.TP
+<\fICRATE_NAME\fR>
+Name of the crate to package
+.TP
+[\fIVERSION\fR]
+Version of the crate to package; may contain dependency operators. If empty string, resolves to the latest version. If given here, i.e. not omitted then print the package name as if the config option `semver_suffix` was set to true
diff --git a/manpages/debcargo-extract.1 b/manpages/debcargo-extract.1
new file mode 100644 (file)
index 0000000..5855d13
--- /dev/null
@@ -0,0 +1,25 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo-extract 1  "extract " 
+.SH NAME
+debcargo\-extract \- Extract only a crate, without any other transformations
+.SH SYNOPSIS
+\fBdebcargo extract\fR [\fB\-\-config\fR] [\fB\-\-directory\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fICRATE_NAME\fR> [\fIVERSION\fR] 
+.SH DESCRIPTION
+Extract only a crate, without any other transformations
+.SH OPTIONS
+.TP
+\fB\-\-config\fR \fI<CONFIG>\fR
+TOML file providing package\-specific options
+.TP
+\fB\-\-directory\fR \fI<DIRECTORY>\fR
+Output directory for the package. The orig tarball is named according to Debian conventions in the parent directory of this directory
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
+.TP
+<\fICRATE_NAME\fR>
+Name of the crate to package
+.TP
+[\fIVERSION\fR]
+Version of the crate to package; may contain dependency operators. If empty string or omitted, resolves to the latest version
diff --git a/manpages/debcargo-package.1 b/manpages/debcargo-package.1
new file mode 100644 (file)
index 0000000..824a85d
--- /dev/null
@@ -0,0 +1,34 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo-package 1  "package " 
+.SH NAME
+debcargo\-package \- Package a Rust crate for Debian
+.SH SYNOPSIS
+\fBdebcargo package\fR [\fB\-\-config\fR] [\fB\-\-directory\fR] [\fB\-\-changelog\-ready\fR] [\fB\-\-copyright\-guess\-harder\fR] [\fB\-\-no\-overlay\-write\-back\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fICRATE_NAME\fR> [\fIVERSION\fR] 
+.SH DESCRIPTION
+Package a Rust crate for Debian
+.SH OPTIONS
+.TP
+\fB\-\-config\fR \fI<CONFIG>\fR
+TOML file providing package\-specific options
+.TP
+\fB\-\-directory\fR \fI<DIRECTORY>\fR
+Output directory for the package. The orig tarball is named according to Debian conventions in the parent directory of this directory
+.TP
+\fB\-\-changelog\-ready\fR
+Assume the changelog is already bumped, and leave it alone
+.TP
+\fB\-\-copyright\-guess\-harder\fR
+Guess extra values for d/copyright. Might be slow
+.TP
+\fB\-\-no\-overlay\-write\-back\fR
+Don\*(Aqt write back hint files or d/changelog to the source overlay directory
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
+.TP
+<\fICRATE_NAME\fR>
+Name of the crate to package
+.TP
+[\fIVERSION\fR]
+Version of the crate to package; may contain dependency operators. If empty string or omitted, resolves to the latest version
diff --git a/manpages/debcargo-update-dependencies.1 b/manpages/debcargo-update-dependencies.1
new file mode 100644 (file)
index 0000000..cac3313
--- /dev/null
@@ -0,0 +1,34 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo-update-dependencies 1  "update-dependencies " 
+.SH NAME
+debcargo\-update\-dependencies \- Update debian/control Build\-Depends from workspace Cargo.toml files
+.SH SYNOPSIS
+\fBdebcargo update\-dependencies\fR [\fB\-\-drop\-unreferenced\fR] [\fB\-\-include\-local\-crates\fR] [\fB\-\-features\fR] [\fB\-\-all\-features\fR] [\fB\-\-no\-default\-features\fR] [\fB\-\-allow\-prerelease\-deps\fR] [\fB\-\-include\-dev\-dependencies\fR] [\fB\-h\fR|\fB\-\-help\fR] 
+.SH DESCRIPTION
+Update debian/control Build\-Depends from workspace Cargo.toml files
+.SH OPTIONS
+.TP
+\fB\-\-drop\-unreferenced\fR
+Drop Rust development package dependencies that are not referenced by any workspace crate
+.TP
+\fB\-\-include\-local\-crates\fR
+Include dependencies for crates that are present as workspace members
+.TP
+\fB\-\-features\fR \fI<FEATURES>\fR
+Features to include in dependencies (can be specified multiple times)
+.TP
+\fB\-\-all\-features\fR
+Include all features in dependencies
+.TP
+\fB\-\-no\-default\-features\fR
+Do not include default feature in dependencies
+.TP
+\fB\-\-allow\-prerelease\-deps\fR
+Allow prerelease versions of dependencies
+.TP
+\fB\-\-include\-dev\-dependencies\fR
+Include dev\-dependencies
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
diff --git a/manpages/debcargo-update.1 b/manpages/debcargo-update.1
new file mode 100644 (file)
index 0000000..695f033
--- /dev/null
@@ -0,0 +1,13 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo-update 1  "update " 
+.SH NAME
+debcargo\-update \- Update the user\*(Aqs default crates.io index, outside of a workspace
+.SH SYNOPSIS
+\fBdebcargo update\fR [\fB\-h\fR|\fB\-\-help\fR] 
+.SH DESCRIPTION
+Update the user\*(Aqs default crates.io index, outside of a workspace
+.SH OPTIONS
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
diff --git a/manpages/debcargo.1 b/manpages/debcargo.1
new file mode 100644 (file)
index 0000000..12244e7
--- /dev/null
@@ -0,0 +1,40 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo 1  "debcargo 2.8.1" 
+.SH NAME
+debcargo \- Package Rust crates for Debian.
+.SH SYNOPSIS
+\fBdebcargo\fR [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] <\fIsubcommands\fR>
+.SH DESCRIPTION
+Package Rust crates for Debian.
+.SH OPTIONS
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print version
+.SH SUBCOMMANDS
+.TP
+debcargo\-update(1)
+Update the user\*(Aqs default crates.io index, outside of a workspace
+.TP
+debcargo\-deb\-src\-name(1)
+Print the Debian package name for a crate
+.TP
+debcargo\-extract(1)
+Extract only a crate, without any other transformations
+.TP
+debcargo\-package(1)
+Package a Rust crate for Debian
+.TP
+debcargo\-build\-order(1)
+Print the transitive dependencies of a package in topological order
+.TP
+debcargo\-deb\-dependencies(1)
+Print the dependencies of a package in d/control format
+.TP
+debcargo\-update\-dependencies(1)
+Update debian/control Build\-Depends from workspace Cargo.toml files
+.SH VERSION
+v2.8.1
diff --git a/src/bin/debcargo.rs b/src/bin/debcargo.rs
new file mode 100644 (file)
index 0000000..94494e3
--- /dev/null
@@ -0,0 +1,90 @@
+use clap::{crate_version, Parser};
+use itertools::Itertools;
+use nu_ansi_term::Color::Red;
+
+use debcargo::cli::{Cli, Opt};
+use debcargo::crates::CrateInfo;
+use debcargo::debian::DebInfo;
+use debcargo::errors::Result;
+use debcargo::package::PackageProcess;
+use debcargo::{
+    build_order::build_order, crates::invalidate_crates_io_cache,
+    deb_dependencies::deb_dependencies,
+};
+
+#[cfg(feature = "update-dependencies")]
+use debcargo::update_dependencies::update_dependencies;
+#[cfg(feature = "update-dependencies")]
+use Opt::UpdateDependencies;
+use Opt::{BuildOrder, DebDependencies, DebSrcName, Extract, Package, Update};
+
+#[test]
+fn verify_app() {
+    use clap::CommandFactory;
+    Cli::command().debug_assert()
+}
+
+fn real_main() -> Result<()> {
+    let m = Cli::parse();
+    match m.command {
+        Update => invalidate_crates_io_cache(),
+        DebSrcName {
+            crate_name,
+            version,
+        } => {
+            let crate_info = CrateInfo::new_with_update(&crate_name, version.as_deref(), false)?;
+            let deb_info = DebInfo::new(&crate_info, crate_version!(), version.is_some(), None);
+            println!("{}", deb_info.package_name());
+            Ok(())
+        }
+        Extract { init, extract } => {
+            log::info!("preparing crate info");
+            let mut process = PackageProcess::init(init)?;
+            log::info!("extracting crate");
+            process.extract(extract)?;
+            Ok(())
+        }
+        Package {
+            init,
+            extract,
+            finish,
+        } => {
+            log::info!("preparing crate info");
+            let mut process = PackageProcess::init(init)?;
+            log::info!("extracting crate");
+            process.extract(extract)?;
+            log::info!("applying overlay and patches");
+            process.apply_overrides()?;
+            log::info!("preparing orig tarball");
+            process.prepare_orig_tarball()?;
+            log::info!("preparing debian folder");
+            process.prepare_debian_folder(&finish)?;
+            process.post_package_checks()
+        }
+        BuildOrder { args } => {
+            let build_order = build_order(&args)?;
+            for v in &build_order {
+                println!("{v}");
+            }
+            Ok(())
+        }
+        DebDependencies { args } => {
+            let (toolchain_deps, dependencies) = deb_dependencies(&args)?;
+            println!(
+                "{}",
+                toolchain_deps.into_iter().chain(dependencies).join(", ")
+            );
+            Ok(())
+        }
+        #[cfg(feature = "update-dependencies")]
+        UpdateDependencies { args } => update_dependencies(&args),
+    }
+}
+
+fn main() {
+    env_logger::init();
+    if let Err(e) = real_main() {
+        eprintln!("{}", Red.bold().paint(format!("debcargo failed: {e:?}")));
+        std::process::exit(1);
+    }
+}
diff --git a/src/build_order.rs b/src/build_order.rs
new file mode 100644 (file)
index 0000000..782ccb3
--- /dev/null
@@ -0,0 +1,290 @@
+use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque};
+use std::fmt;
+use std::path::{Path, PathBuf};
+
+use anyhow::Context;
+use cargo::core::{Dependency, PackageId};
+use cargo::util::interning::InternedString;
+use clap::{Parser, ValueEnum};
+
+use crate::config::Config;
+use crate::crates::{
+    all_dependencies_and_features, crate_name_ver_to_dep, show_dep, transitive_deps, CrateDepInfo,
+    CrateInfo,
+};
+use crate::debian::control::base_deb_name;
+use crate::errors::Result;
+use crate::package::{PackageExtractArgs, PackageProcess};
+use crate::util;
+use ResolveType::{BinaryAllForDebianTesting, SourceForDebianUnstable};
+
+#[derive(Debug, Clone, Copy, ValueEnum)]
+#[value(rename_all = "verbatim")]
+pub enum ResolveType {
+    SourceForDebianUnstable,
+    BinaryAllForDebianTesting,
+}
+
+#[derive(Debug, Clone, Parser)]
+pub struct BuildOrderArgs {
+    /// Name of the crate to package.
+    crate_name: String,
+    /// Version of the crate to package; may contain dependency operators.
+    version: Option<String>,
+    /// Directory for configs. The config subdirectory for a given crate is
+    /// looked up by their crate name and version, from more specific to less
+    /// specific, e.g. <crate>-1.2.3, then <crate>-1.2, then <crate>-1 and
+    /// finally <crate>. The config file is read from the debian/debcargo.toml
+    /// subpath of the looked-up subdirectory.
+    #[arg(long)]
+    config_dir: Option<PathBuf>,
+    /// Resolution type
+    #[arg(value_enum, long, default_value = "SourceForDebianUnstable")]
+    resolve_type: ResolveType,
+    /// Emulate resolution as if every package were built with --collapse-features.
+    #[arg(long)]
+    emulate_collapse_features: bool,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+struct PackageIdFeat(PackageId, &'static str);
+
+impl fmt::Display for PackageIdFeat {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}@{}/{}", self.0.name(), self.0.version(), self.1)
+    }
+}
+
+// First result: if somebody build-depends on us, what do they first need to build?
+// Second result: what other packages need to go into Debian Testing before us?
+fn get_build_deps(
+    crate_details: &(CrateInfo, CrateDepInfo, Config),
+    package: &PackageIdFeat,
+    resolve_type: ResolveType,
+    emulate_collapse_features: bool,
+) -> Result<(Vec<Dependency>, Vec<Dependency>)> {
+    let (_, crate_dep_info, config) = crate_details;
+    let all_deps = crate_dep_info
+        .iter()
+        .flat_map(|(_, v)| v.1.iter())
+        .cloned()
+        .collect::<HashSet<_>>();
+    let feature_deps: HashSet<Dependency> =
+        HashSet::from_iter(transitive_deps(crate_dep_info, package.1)?.1);
+    let additional_deps = if emulate_collapse_features || config.collapse_features {
+        all_deps.clone()
+    } else {
+        // TODO: if build_depends_features is an override, use that instead of "default"
+        // TODO: also deprecate build_depends_excludes
+        HashSet::from_iter(transitive_deps(crate_dep_info, "default")?.1)
+    };
+    let hard_deps = feature_deps
+        .union(&additional_deps)
+        .cloned()
+        .collect::<Vec<_>>();
+    match resolve_type {
+        SourceForDebianUnstable => Ok((hard_deps, vec![])),
+        BinaryAllForDebianTesting => {
+            let mut soft_deps = all_deps;
+            for h in &hard_deps {
+                soft_deps.remove(h);
+            }
+            Ok((hard_deps, soft_deps.into_iter().collect::<Vec<_>>()))
+        }
+    }
+}
+
+fn dep_features(dep: &Dependency) -> Vec<&'static str> {
+    let mut feats = dep
+        .features()
+        .iter()
+        .map(InternedString::as_str)
+        .collect::<Vec<_>>();
+    if dep.uses_default_features() {
+        feats.push("default");
+    }
+    feats.push(""); // bare-bones library with no features
+    feats
+}
+
+fn find_config(config_dir: &Path, id: PackageId) -> Result<(Option<PathBuf>, Config)> {
+    let name = base_deb_name(&id.name());
+    let version = id.version();
+    let candidates = [
+        format!(
+            "{}-{}.{}.{}",
+            name, version.major, version.minor, version.patch
+        ),
+        format!("{}-{}.{}", name, version.major, version.minor),
+        format!("{}-{}", name, version.major),
+        name,
+    ];
+    for c in candidates {
+        let path = config_dir.join(c).join("debian").join("debcargo.toml");
+        if path.is_file() {
+            let config = Config::parse(&path).context("failed to parse debcargo.toml")?;
+            log::debug!("using config for {id}: {path:?}");
+            return Ok((Some(path), config));
+        }
+    }
+    Ok((None, Config::default()))
+}
+
+fn resolve_info(
+    infos: &mut BTreeMap<PackageId, (CrateInfo, CrateDepInfo, Config)>,
+    cache: &mut HashMap<Dependency, PackageId>,
+    config_dir: Option<&Path>,
+    dependency: &Dependency,
+    update: bool,
+) -> Result<PackageId> {
+    if let Some(id) = cache.get(dependency) {
+        return Ok(*id);
+    }
+
+    // resolve dependency
+    let info = CrateInfo::new_from_dependency(dependency, update)?;
+    let id = info.package_id();
+    cache.insert(dependency.clone(), id);
+
+    // insert info if it's not already there
+    if let std::collections::btree_map::Entry::Vacant(e) = infos.entry(id) {
+        let id = *e.key();
+        let default_config = Config::default();
+        let (config_path, config) = if let Some(config_dir) = config_dir {
+            let (config_path, config) = find_config(config_dir, id)?;
+            if config_path.is_none() {
+                (None, default_config)
+            } else {
+                (config_path, config)
+            }
+        } else {
+            (None, default_config)
+        };
+        let (info, config) = if config_path.is_none() {
+            (info, config)
+        } else {
+            let mut process = PackageProcess::new(info, config_path, config)?;
+            let tempdir = tempfile::Builder::new()
+                .prefix("debcargo")
+                .tempdir_in(".")?;
+            process.extract(PackageExtractArgs {
+                directory: Some(tempdir.path().to_path_buf()),
+            })?;
+            process.apply_overrides()?;
+            (process.crate_info, process.config)
+        };
+        let dep_info = all_dependencies_and_features(info.manifest());
+        e.insert((info, dep_info, config));
+    }
+    Ok(id)
+}
+
+pub fn build_order(args: &BuildOrderArgs) -> Result<Vec<PackageId>> {
+    let crate_name = &args.crate_name;
+    let version = args.version.as_deref();
+    let config_dir = args.config_dir.as_deref();
+
+    let mut infos = BTreeMap::new();
+    let mut cache = HashMap::new();
+    let seed_dep = crate_name_ver_to_dep(crate_name, version)?;
+    let seed_id = resolve_info(&mut infos, &mut cache, config_dir, &seed_dep, true)?;
+
+    let mut next = |idf: &PackageIdFeat| -> Result<(Vec<PackageIdFeat>, Vec<PackageIdFeat>)> {
+        log::trace!("{idf} getting build deps..");
+        let (hard, soft) = get_build_deps(
+            infos
+                .get(&idf.0)
+                .expect("build_order next called without crate info"),
+            idf,
+            args.resolve_type,
+            args.emulate_collapse_features,
+        )?;
+        log::trace!("{} hard-dep: {}", idf, util::show_vec_with(&hard, show_dep));
+        if !soft.is_empty() {
+            log::trace!("{} soft-dep: {}", idf, util::show_vec_with(&soft, show_dep));
+        }
+        // note: we might resolve the same crate-version several times;
+        // this is expected, since different dependencies (with different
+        // version ranges) might resolve into the same crate-version
+        let mut hard_p = Vec::new();
+        for dep in hard {
+            let id = resolve_info(&mut infos, &mut cache, config_dir, &dep, false)?;
+            for f in dep_features(&dep) {
+                hard_p.push(PackageIdFeat(id, f));
+            }
+        }
+        let mut soft_p = Vec::new();
+        for dep in soft {
+            let id = resolve_info(&mut infos, &mut cache, config_dir, &dep, false)?;
+            for f in dep_features(&dep) {
+                soft_p.push(PackageIdFeat(id, f));
+            }
+        }
+        log::trace!("{} hard-dep resolve: {}", idf, util::show_vec(&hard_p));
+        if !soft_p.is_empty() {
+            log::trace!("{} soft-dep resolve: {}", idf, util::show_vec(&soft_p));
+        }
+        Ok((hard_p, soft_p))
+    };
+    let mut i = 0;
+    let mut log = |remaining: &VecDeque<_>, graph: &BTreeMap<_, _>| {
+        i += 1;
+        if i % 16 == 0 {
+            debcargo_info!(
+                "debcargo build-order: resolving dependencies: done: {}, todo: {}",
+                graph.len(),
+                remaining.len()
+            );
+        }
+        Ok(())
+    };
+
+    let succ_with_features =
+        util::graph_from_succ([PackageIdFeat(seed_id, "")], &mut next, &mut log)?;
+    log::trace!("succ_with_features: {succ_with_features:#?}");
+
+    let succ = util::succ_proj(&succ_with_features, |x| x.0);
+    let pred = util::succ_to_pred(&succ);
+    let roots = succ
+        .iter()
+        .filter_map(|(k, v)| if v.is_empty() { Some(*k) } else { None })
+        .collect::<BTreeSet<_>>();
+    // swap pred/succ for call to topo_sort since we want reverse topo order
+    let build_order = match util::topo_sort(roots, &pred, succ.clone()) {
+        Ok(r) => r,
+        Err(remain) => {
+            log::error!(
+                "topo_sort got cyclic graph: {:#?}",
+                remain
+                    .into_iter()
+                    .map(|(k, vv)| (
+                        k.to_string(),
+                        vv.into_iter()
+                            .map(|v| v.to_string())
+                            .collect::<BTreeSet<_>>()
+                    ))
+                    .collect::<BTreeMap<_, _>>()
+            );
+            debcargo_bail!(
+                "topo_sort got cyclic graph; you'll need to patch the crate(s) to break the cycle."
+            )
+        }
+    };
+
+    // sanity check
+    for p in &build_order {
+        if infos.remove(p).is_none() {
+            log::error!("extra package in build-order not in infos: {p}");
+        }
+    }
+    for (p, _) in infos {
+        log::error!(
+            "leftover infos not used in build-order: {}, succ: {}, pred: {}",
+            p,
+            util::show_vec(succ.get(&p).into_iter().flatten()),
+            util::show_vec(pred.get(&p).into_iter().flatten()),
+        );
+    }
+
+    Ok(build_order)
+}
diff --git a/src/cli.rs b/src/cli.rs
new file mode 100644 (file)
index 0000000..4fe7def
--- /dev/null
@@ -0,0 +1,73 @@
+use clap::{builder::styling::AnsiColor, builder::Styles, Parser, Subcommand};
+
+use crate::{
+    build_order::BuildOrderArgs,
+    deb_dependencies::DebDependenciesArgs,
+    package::{PackageExecuteArgs, PackageExtractArgs, PackageInitArgs},
+};
+
+#[cfg(feature = "update-dependencies")]
+use crate::update_dependencies::UpdateDependenciesArgs;
+
+const CLI_STYLE: Styles = Styles::styled()
+    .header(AnsiColor::Yellow.on_default())
+    .usage(AnsiColor::Green.on_default())
+    .literal(AnsiColor::Green.on_default())
+    .placeholder(AnsiColor::Green.on_default());
+
+#[derive(Debug, Clone, Parser)]
+#[command(name = "debcargo", about = "Package Rust crates for Debian.")]
+#[command(version)]
+#[command(styles = CLI_STYLE)]
+pub struct Cli {
+    #[command(subcommand)]
+    pub command: Opt,
+}
+
+#[derive(Debug, Clone, Subcommand)]
+pub enum Opt {
+    /// Update the user's default crates.io index, outside of a workspace.
+    Update,
+    /// Print the Debian package name for a crate.
+    DebSrcName {
+        /// Name of the crate to package.
+        crate_name: String,
+        /// Version of the crate to package; may contain dependency operators.
+        /// If empty string, resolves to the latest version. If given here,
+        /// i.e. not omitted then print the package name as if the config
+        /// option `semver_suffix` was set to true.
+        version: Option<String>,
+    },
+    /// Extract only a crate, without any other transformations.
+    Extract {
+        #[command(flatten)]
+        init: PackageInitArgs,
+        #[command(flatten)]
+        extract: PackageExtractArgs,
+    },
+    /// Package a Rust crate for Debian.
+    Package {
+        #[command(flatten)]
+        init: PackageInitArgs,
+        #[command(flatten)]
+        extract: PackageExtractArgs,
+        #[command(flatten)]
+        finish: PackageExecuteArgs,
+    },
+    /// Print the transitive dependencies of a package in topological order.
+    BuildOrder {
+        #[command(flatten)]
+        args: BuildOrderArgs,
+    },
+    /// Print the dependencies of a package in d/control format
+    DebDependencies {
+        #[command(flatten)]
+        args: DebDependenciesArgs,
+    },
+    /// Update debian/control Build-Depends from workspace Cargo.toml files
+    #[cfg(feature = "update-dependencies")]
+    UpdateDependencies {
+        #[command(flatten)]
+        args: UpdateDependenciesArgs,
+    },
+}
diff --git a/src/config.rs b/src/config.rs
new file mode 100644 (file)
index 0000000..7590d7c
--- /dev/null
@@ -0,0 +1,407 @@
+use serde::de::IgnoredAny;
+use serde::Deserialize;
+use toml;
+
+use crate::errors::Result;
+
+use std::borrow::Cow;
+use std::collections::HashMap;
+use std::ffi::OsStr;
+use std::fs::File;
+use std::io::Read;
+use std::path::{Path, PathBuf};
+
+pub const RUST_MAINT: &str =
+    "Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>";
+
+pub const DEFAULT_REPACK_SUFFIX: &str = "dfsg";
+
+#[derive(Deserialize, Debug, Clone)]
+#[serde(default)]
+pub struct Config {
+    pub bin: Option<bool>,
+    pub bin_name: String,
+    pub semver_suffix: bool,
+    pub overlay: Option<PathBuf>,
+    pub excludes: Option<Vec<String>>,
+    pub whitelist: Option<Vec<String>>,
+    pub repack_suffix: Option<String>,
+    pub allow_prerelease_deps: bool,
+    pub crate_src_path: Option<PathBuf>,
+    pub summary: Option<String>,
+    pub description: Option<String>,
+    pub maintainer: String,
+    pub uploaders: Option<Vec<String>>,
+    pub collapse_features: bool,
+    pub requires_root: Option<String>,
+
+    pub source: Option<SourceOverride>,
+    pub packages: HashMap<String, PackageOverride>,
+
+    #[serde(flatten)]
+    pub unknown_fields: HashMap<String, IgnoredAny>,
+}
+
+#[derive(Deserialize, Debug, Clone, Default)]
+pub struct SourceOverride {
+    section: Option<String>,
+    policy: Option<String>,
+    homepage: Option<String>,
+    vcs_git: Option<String>,
+    vcs_browser: Option<String>,
+    build_depends: Option<Vec<String>>,
+    build_depends_arch: Option<Vec<String>>,
+    build_depends_indep: Option<Vec<String>>,
+    build_depends_excludes: Option<Vec<String>>,
+    skip_nocheck: Option<bool>,
+
+    #[serde(flatten)]
+    pub unknown_fields: HashMap<String, IgnoredAny>,
+}
+
+impl SourceOverride {
+    #[expect(clippy::too_many_arguments)]
+    pub fn new(
+        section: Option<String>,
+        policy: Option<String>,
+        homepage: Option<String>,
+        vcs_git: Option<String>,
+        vcs_browser: Option<String>,
+        build_depends: Option<Vec<String>>,
+        build_depends_arch: Option<Vec<String>>,
+        build_depends_indep: Option<Vec<String>>,
+        build_depends_excludes: Option<Vec<String>>,
+        skip_nocheck: Option<bool>,
+    ) -> Self {
+        Self {
+            section,
+            policy,
+            homepage,
+            vcs_git,
+            vcs_browser,
+            build_depends,
+            build_depends_arch,
+            build_depends_indep,
+            build_depends_excludes,
+            skip_nocheck,
+            unknown_fields: HashMap::new(),
+        }
+    }
+}
+#[derive(Deserialize, Debug, Clone, Default)]
+pub struct PackageOverride {
+    section: Option<String>,
+    summary: Option<String>,
+    description: Option<String>,
+    architecture: Option<Vec<String>>,
+    multi_arch: Option<String>,
+    depends: Option<Vec<String>>,
+    recommends: Option<Vec<String>>,
+    suggests: Option<Vec<String>>,
+    provides: Option<Vec<String>>,
+    breaks: Option<Vec<String>>,
+    replaces: Option<Vec<String>>,
+    conflicts: Option<Vec<String>>,
+    extra_lines: Option<Vec<String>>,
+    test_is_broken: Option<bool>,
+    test_architecture: Option<Vec<String>>,
+    test_depends: Option<Vec<String>>,
+
+    #[serde(flatten)]
+    pub unknown_fields: HashMap<String, IgnoredAny>,
+}
+
+impl Default for Config {
+    fn default() -> Self {
+        Config {
+            bin: None,
+            bin_name: "<default>".to_string(),
+            semver_suffix: false,
+            overlay: None,
+            excludes: None,
+            repack_suffix: None,
+            whitelist: None,
+            allow_prerelease_deps: false,
+            crate_src_path: None,
+            summary: None,
+            description: None,
+            maintainer: RUST_MAINT.to_string(),
+            uploaders: None,
+            collapse_features: false,
+            source: None,
+            packages: HashMap::new(),
+            requires_root: None,
+            unknown_fields: HashMap::new(),
+        }
+    }
+}
+
+impl Config {
+    pub fn parse(src: &Path) -> Result<Config> {
+        let mut config_file = File::open(src)?;
+        let mut content = String::new();
+        config_file.read_to_string(&mut content)?;
+
+        let config: Config = toml::from_str(&content)?;
+
+        let mut unknown_fields = Vec::new();
+
+        for field in config.unknown_fields.keys() {
+            unknown_fields.push(field.clone());
+        }
+
+        if let Some(ref source) = config.source {
+            for field in source.unknown_fields.keys() {
+                unknown_fields.push(format!("source.{field}"));
+            }
+        }
+
+        for field in config.packages.keys() {
+            if PackageKey::from_key(field).is_none() {
+                unknown_fields.push(format!("packages.{field}"));
+            }
+        }
+
+        for (name, package) in &config.packages {
+            for field in package.unknown_fields.keys() {
+                unknown_fields.push(format!("packages.{name}.{field}"));
+            }
+        }
+
+        if !unknown_fields.is_empty() {
+            debcargo_warn!(
+                "Warning: Unknown fields in {}: {:?}",
+                src.display(),
+                unknown_fields
+            );
+            debcargo_warn!("         These fields will be ignored. Please check for typos.");
+        }
+
+        Ok(config)
+    }
+
+    pub fn build_bin_package(&self) -> bool {
+        self.bin.unwrap_or(!self.semver_suffix)
+    }
+
+    pub fn overlay_dir(&self, config_path: Option<&Path>) -> Option<PathBuf> {
+        Some(config_path?.parent()?.join(self.overlay.as_ref()?))
+    }
+
+    pub fn crate_src_path(&self, config_path: Option<&Path>) -> Option<PathBuf> {
+        Some(config_path?.parent()?.join(self.crate_src_path.as_ref()?))
+    }
+
+    pub fn orig_tar_excludes(&self) -> Option<&Vec<String>> {
+        self.excludes.as_ref()
+    }
+
+    pub fn orig_tar_whitelist(&self) -> Option<&Vec<String>> {
+        self.whitelist.as_ref()
+    }
+
+    pub fn repack_suffix(&self) -> Option<&str> {
+        self.repack_suffix
+            .as_deref()
+            .or_else(|| self.orig_tar_excludes().and(Some(DEFAULT_REPACK_SUFFIX)))
+    }
+
+    pub fn maintainer(&self) -> &str {
+        self.maintainer.as_str()
+    }
+
+    pub fn uploaders(&self) -> Option<&Vec<String>> {
+        self.uploaders.as_ref()
+    }
+
+    pub fn requires_root(&self) -> Option<&String> {
+        self.requires_root.as_ref()
+    }
+
+    // Source shortcuts
+
+    pub fn section(&self) -> Option<&str> {
+        Some(self.source.as_ref()?.section.as_ref()?)
+    }
+
+    pub fn policy_version(&self) -> Option<&str> {
+        Some(self.source.as_ref()?.policy.as_ref()?)
+    }
+
+    pub fn homepage(&self) -> Option<&str> {
+        Some(self.source.as_ref()?.homepage.as_ref()?)
+    }
+
+    pub fn vcs_git(&self) -> Option<&str> {
+        Some(self.source.as_ref()?.vcs_git.as_ref()?)
+    }
+
+    pub fn vcs_browser(&self) -> Option<&str> {
+        Some(self.source.as_ref()?.vcs_browser.as_ref()?)
+    }
+
+    pub fn build_depends(&self) -> Option<&Vec<String>> {
+        self.source.as_ref()?.build_depends.as_ref()
+    }
+
+    pub fn build_depends_arch(&self) -> Option<&Vec<String>> {
+        self.source.as_ref()?.build_depends_arch.as_ref()
+    }
+
+    pub fn build_depends_indep(&self) -> Option<&Vec<String>> {
+        self.source.as_ref()?.build_depends_indep.as_ref()
+    }
+
+    pub fn build_depends_excludes(&self) -> Option<&Vec<String>> {
+        self.source.as_ref()?.build_depends_excludes.as_ref()
+    }
+
+    pub fn skip_nocheck(&self) -> Option<bool> {
+        self.source.as_ref()?.skip_nocheck
+    }
+
+    // Packages accessors
+
+    pub fn configured_packages(&'_ self) -> impl Iterator<Item = PackageKey<'_>> {
+        self.packages.keys().filter_map(|k| PackageKey::from_key(k))
+    }
+
+    fn with_package<'a, T, F: FnOnce(&'a PackageOverride) -> Option<T>>(
+        &'a self,
+        key: PackageKey,
+        f: F,
+    ) -> Option<T> {
+        self.packages.get(&key.key_string()[..]).and_then(f)
+    }
+
+    pub fn package_section(&self, key: PackageKey) -> Option<&str> {
+        self.with_package(key, |pkg| pkg.section.as_deref())
+    }
+
+    pub fn package_summary(&self, key: PackageKey) -> Option<&str> {
+        self.with_package(key, |pkg| pkg.summary.as_deref())
+    }
+
+    pub fn package_description(&self, key: PackageKey) -> Option<&str> {
+        self.with_package(key, |pkg| pkg.description.as_deref())
+    }
+
+    pub fn package_architecture(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.architecture.as_ref())
+    }
+
+    pub fn package_multi_arch(&self, key: PackageKey) -> Option<&str> {
+        self.with_package(key, |pkg| pkg.multi_arch.as_deref())
+    }
+
+    pub fn package_depends(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.depends.as_ref())
+    }
+
+    pub fn package_recommends(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.recommends.as_ref())
+    }
+
+    pub fn package_suggests(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.suggests.as_ref())
+    }
+
+    pub fn package_provides(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.provides.as_ref())
+    }
+
+    pub fn package_breaks(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.breaks.as_ref())
+    }
+
+    pub fn package_replaces(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.replaces.as_ref())
+    }
+
+    pub fn package_conflicts(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.conflicts.as_ref())
+    }
+
+    pub fn package_extra_lines(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.extra_lines.as_ref())
+    }
+
+    pub fn package_test_is_broken(&self, key: PackageKey) -> Option<bool> {
+        self.with_package(key, |pkg| pkg.test_is_broken)
+    }
+
+    pub fn package_test_architecture(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.test_architecture.as_ref())
+    }
+
+    pub fn package_test_depends(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.test_depends.as_ref())
+    }
+}
+
+pub fn package_field_for_feature<'a, 'b, F: Fn(PackageKey) -> Option<&'a Vec<String>>>(
+    get_field: F,
+    feature: PackageKey<'b>,
+    f_provides: &'b [&'b str],
+) -> impl Iterator<Item = String> + use<'a, 'b, F> {
+    Some(feature)
+        .into_iter()
+        .chain(f_provides.iter().map(|s| PackageKey::feature(s)))
+        .flat_map(move |f| get_field(f).into_iter().flatten())
+        .map(ToString::to_string)
+}
+
+#[derive(Clone, Copy)]
+pub enum PackageKey<'a> {
+    Bin,
+    BareLib,
+    FeatureLib(&'a str),
+    Extra(&'a str),
+}
+
+impl<'a> PackageKey<'a> {
+    pub fn feature(f: &'a str) -> PackageKey<'a> {
+        use self::PackageKey::{BareLib, FeatureLib};
+        if f.is_empty() {
+            BareLib
+        } else {
+            FeatureLib(f)
+        }
+    }
+
+    pub fn from_key(k: &'a str) -> Option<PackageKey<'a>> {
+        use self::PackageKey::{BareLib, Bin, Extra, FeatureLib};
+        Some(match k {
+            "bin" => Bin,
+            "lib" => BareLib,
+            _ => {
+                if let Some(feature) = k.strip_prefix("lib+") {
+                    FeatureLib(feature)
+                } else if let Some(package) = k.strip_prefix("extra+") {
+                    Extra(package)
+                } else {
+                    return None;
+                }
+            }
+        })
+    }
+
+    fn key_string(&self) -> Cow<'static, str> {
+        use self::PackageKey::{BareLib, Bin, Extra, FeatureLib};
+        match self {
+            Bin => "bin".into(),
+            BareLib => "lib".into(),
+            FeatureLib(feature) => format!("lib+{feature}").into(),
+            Extra(package) => format!("extra+{package}").into(),
+        }
+    }
+}
+
+pub fn testing_ignore_debpolv() -> bool {
+    std::env::var_os("DEBCARGO_TESTING_IGNORE_DEBIAN_POLICY_VIOLATION").as_deref()
+        == Some(OsStr::new("1"))
+}
+
+pub fn testing_ruzt() -> bool {
+    std::env::var_os("DEBCARGO_TESTING_RUZT").as_deref() == Some(OsStr::new("1"))
+}
diff --git a/src/crates.rs b/src/crates.rs
new file mode 100644 (file)
index 0000000..256fb4d
--- /dev/null
@@ -0,0 +1,882 @@
+use anyhow::{format_err, Error};
+use cargo::{
+    core::{
+        manifest::ManifestMetadata, registry::PackageRegistry, resolver::features::CliFeatures,
+        Dependency, EitherManifest, FeatureValue, Manifest, Package, PackageId, Registry, SourceId,
+        Summary, Target, TargetKind, Workspace,
+    },
+    ops::{self, PackageMessageFormat, PackageOpts, Packages},
+    sources::{
+        source::{MaybePackage, QueryKind, Source},
+        IndexSummary, RegistrySource, SourceConfigMap,
+    },
+    util::{
+        cache_lock::CacheLockMode, interning::InternedString, toml::read_manifest, FileLock,
+        GlobalContext,
+    },
+};
+use filetime::{set_file_times, FileTime};
+use flate2::read::GzDecoder;
+use glob::Pattern;
+use itertools::Itertools;
+use regex::Regex;
+use semver::Version;
+use tar::Archive;
+use tempfile;
+
+use crate::config::testing_ignore_debpolv;
+use crate::errors::Result;
+use cargo::util::Filesystem;
+use std::collections::{BTreeMap, HashSet};
+use std::fs;
+use std::io::{self, Read};
+use std::path::Path;
+use std::{self, ffi::OsStr};
+
+pub struct CrateInfo {
+    // only used for to_registry_toml in extract_crate. DO NOT USE ELSEWHERE
+    package: Package,
+    // allows overriding package.manifest() e.g. via patches
+    manifest: Manifest,
+    crate_file: FileLock,
+    context: GlobalContext,
+    source_id: SourceId,
+    excludes: Vec<String>,
+    includes: Vec<String>,
+}
+
+pub type CrateDepInfo = BTreeMap<
+    &'static str, // name of feature / optional dependency,
+    // or "" for the base package w/ no default features, guaranteed to be in the map
+    (
+        Vec<&'static str>, // dependencies: other features (of the current package)
+        Vec<Dependency>,
+    ),
+>;
+
+fn fetch_candidates(registry: &mut PackageRegistry, dep: &Dependency) -> Result<Vec<IndexSummary>> {
+    let mut summaries = match registry.query_vec(dep, QueryKind::Exact) {
+        std::task::Poll::Ready(res) => res?,
+        std::task::Poll::Pending => {
+            registry.block_until_ready()?;
+            return fetch_candidates(registry, dep);
+        }
+    };
+    summaries.sort_by(|a, b| b.package_id().partial_cmp(&a.package_id()).unwrap());
+    Ok(summaries)
+}
+
+pub fn invalidate_crates_io_cache() -> Result<()> {
+    let context = GlobalContext::default()?;
+    let _lock = context.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;
+    let source_id = SourceId::crates_io_maybe_sparse_http(&context)?;
+    let yanked_whitelist = HashSet::new();
+    let mut r = RegistrySource::remote(source_id, &yanked_whitelist, &context)?;
+    r.invalidate_cache();
+    Ok(())
+}
+
+pub fn crate_name_ver_to_dep(crate_name: &str, version: Option<&str>) -> Result<Dependency> {
+    // note: this forces a network call
+    let context = GlobalContext::default()?;
+    let source_id = SourceId::crates_io_maybe_sparse_http(&context)?;
+    let version = version.and_then(|v| {
+        if v.is_empty() {
+            None
+        } else if v.starts_with(|c: char| c.is_ascii_digit()) {
+            Some(["=", v].concat())
+        } else {
+            Some(v.to_string())
+        }
+    });
+    Dependency::parse(crate_name, version.as_deref(), source_id)
+}
+
+// attempt to map back a version requirement to a version that can be used as last resort
+// fallback in case all versions satisfying the requirement are yanked
+fn ver_req_to_ver(dep: &Dependency) -> Option<Version> {
+    match dep.version_req() {
+        // if any version would satisfy the dep, but all of them are yanked, we probably don't want
+        // to use this crate anyway ;)
+        cargo::util::OptVersionReq::Any => None,
+        // a regular version requirement is only useful if it has a single element
+        cargo::util::OptVersionReq::Req(req) if req.comparators.len() == 1 => {
+            let comp = req.comparators.first().unwrap();
+            match comp.op {
+                // these are all satisfied by the full version, if one is set
+                semver::Op::Exact
+                | semver::Op::GreaterEq
+                | semver::Op::LessEq
+                | semver::Op::Tilde
+                | semver::Op::Caret => {
+                    if let Some(minor) = comp.minor {
+                        // if the requirement comes with a full version extract it
+                        comp.patch.map(|patch| Version {
+                            major: comp.major,
+                            minor,
+                            patch,
+                            pre: comp.pre.clone(),
+                            build: semver::BuildMetadata::default(),
+                        })
+                    } else {
+                        // we'd have to guess here.
+                        None
+                    }
+                }
+                // Greater, Less or Wildcard all require guessing as well
+                _ => None,
+            }
+        }
+        // requirements with multiple constraints
+        cargo::util::OptVersionReq::Req(_) => None,
+        // locked requirements contain an exact version
+        cargo::util::OptVersionReq::Locked(ver, _) => Some(ver.clone()),
+        // precise requirements contain an exact version
+        cargo::util::OptVersionReq::Precise(ver, _) => Some(ver.clone()),
+    }
+}
+
+pub fn show_dep(dep: &Dependency) -> String {
+    format!("{} {}", dep.package_name(), dep.version_req())
+}
+
+impl CrateInfo {
+    pub fn new(crate_name: &str, version: Option<&str>) -> Result<CrateInfo> {
+        CrateInfo::new_with_update(crate_name, version, true)
+    }
+
+    pub fn new_with_local_crate(
+        crate_name: &str,
+        version: Option<&str>,
+        crate_path: &Path,
+    ) -> Result<CrateInfo> {
+        let context = GlobalContext::default()?;
+        let crate_path = crate_path.canonicalize()?;
+        let source_id = SourceId::for_path(&crate_path)?;
+
+        let (package, crate_file) = {
+            let yanked_whitelist = HashSet::new();
+
+            let mut source = source_id.load(&context, &yanked_whitelist)?;
+
+            let package_id = match version {
+                None => {
+                    let dep = Dependency::parse(crate_name, None, source_id)?;
+                    let mut package_id: Option<PackageId> = None;
+                    loop {
+                        match source.query(&dep, QueryKind::Exact, &mut |p| {
+                            package_id = Some(p.package_id());
+                        }) {
+                            std::task::Poll::Ready(res) => {
+                                res?;
+                                break;
+                            }
+                            std::task::Poll::Pending => {
+                                source.block_until_ready()?;
+                            }
+                        }
+                    }
+                    package_id.unwrap()
+                }
+                Some(version) => {
+                    let version = version.parse::<Version>()?;
+                    PackageId::new(crate_name.into(), version, source_id)
+                }
+            };
+
+            let maybe_package = source.download(package_id)?;
+            let package = match maybe_package {
+                MaybePackage::Ready(p) => Ok(p),
+                _ => Err(format_err!(
+                    "Failed to 'download' local crate {} from {}",
+                    crate_name,
+                    crate_path.display()
+                )),
+            }?;
+
+            let crate_file = {
+                let workspace = Workspace::ephemeral(package.clone(), &context, None, true)?;
+
+                let opts = PackageOpts {
+                    gctx: &context,
+                    verify: false,
+                    list: false,
+                    check_metadata: true,
+                    allow_dirty: true,
+                    cli_features: CliFeatures::from_command_line(&[], true, false)?,
+                    jobs: None,
+                    targets: Vec::new(),
+                    to_package: Packages::Default,
+                    keep_going: false,
+                    reg_or_index: None,
+                    dry_run: false,
+                    include_lockfile: false,
+                    fmt: PackageMessageFormat::Human,
+                };
+                ops::package(&workspace, &opts)?;
+
+                let filename = format!("{}-{}.crate", crate_name, package_id.version());
+                workspace
+                    .target_dir()
+                    .join("package")
+                    .open_rw_exclusive_create(filename, &context, "crate file")?
+            };
+
+            (package, crate_file)
+        };
+
+        let manifest = package.manifest().clone();
+
+        Ok(CrateInfo {
+            package,
+            manifest,
+            crate_file,
+            context,
+            source_id,
+            excludes: vec![],
+            includes: vec![],
+        })
+    }
+
+    pub fn new_with_update(
+        crate_name: &str,
+        version: Option<&str>,
+        update: bool,
+    ) -> Result<CrateInfo> {
+        let dep = crate_name_ver_to_dep(crate_name, version)?;
+        Self::new_from_dependency(&dep, update)
+    }
+
+    pub fn new_from_dependency(dependency: &Dependency, update: bool) -> Result<CrateInfo> {
+        let mut context = GlobalContext::default()?;
+        if !update {
+            // unfriendly API from cargo; we'll have to make do with it for
+            // now as there is no other alternative
+            context.configure(
+                0,
+                false,
+                None,
+                false,
+                false,
+                true, // offline
+                &context.target_dir()?.map(Filesystem::into_path_unlocked),
+                &[],
+                &[],
+            )?;
+        }
+
+        let source_id = SourceId::crates_io_maybe_sparse_http(&context)?;
+        let registry_name = format!(
+            "{}-{}",
+            source_id.url().host_str().unwrap_or(""),
+            cargo::util::hex::short_hash(&source_id)
+        );
+        let get_package_info = |context: &GlobalContext,
+                                possibly_yanked_ver: Option<&Version>|
+         -> Result<_> {
+            let lock = context.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;
+            let mut registry =
+                PackageRegistry::new_with_source_config(context, SourceConfigMap::new(context)?)?;
+
+            // if we have some exact version that should satisfy our dependency requirements, and
+            // we are on our third attempt of retrieving the crate info from the registry, add this
+            // version to the yanked whitelist as a last resort
+            if let Some(ver) = possibly_yanked_ver {
+                let pkgids = vec![PackageId::new(
+                    dependency.package_name(),
+                    ver.clone(),
+                    dependency.source_id(),
+                )];
+                debcargo_warn!(
+                    "Adding {} to yanked whitelist as last resort..",
+                    pkgids.first().unwrap()
+                );
+                registry.add_to_yanked_whitelist(pkgids.into_iter());
+            }
+            registry.lock_patches();
+            let summaries = fetch_candidates(&mut registry, dependency)?;
+            drop(lock);
+            let pkgids = summaries.into_iter().map(|s| s.package_id()).collect_vec();
+            let pkgid = pkgids.iter().max().ok_or_else(|| {
+                format_err!(
+                    concat!(
+                        "Couldn't find any crate matching {}\n",
+                        "Try `debcargo update` to update the crates.io index."
+                    ),
+                    show_dep(dependency)
+                )
+            })?;
+            let pkgset = registry.get(pkgids.as_slice())?;
+            let package = pkgset.get_one(*pkgid)?;
+
+            let manifest = package.manifest();
+            for f in dependency.features() {
+                // apparently, if offline is set then cargo sometimes selects
+                // an offline-available version that doesn't satisfy the
+                // requested features. this is dumb. if it happens, then we
+                // retry with online allowed.
+                if !manifest.summary().features().contains_key(f) {
+                    debcargo_bail!(
+                        "resolve ({} {}) -> ({}) failed to pick up required feature ({})\n\
+                        This can happen with very old or yanked crates. Try patching one of \
+                        its dependants, to drop or update the offending dependency.",
+                        dependency.package_name(),
+                        dependency.version_req(),
+                        pkgid,
+                        f,
+                    )
+                }
+            }
+            let filename = format!("{}-{}.crate", pkgid.name(), pkgid.version());
+            let crate_file = context
+                .registry_cache_path()
+                .join(&registry_name)
+                .open_ro_shared(&filename, context, &filename)?;
+            Ok((package.clone(), manifest.clone(), crate_file))
+        };
+        // if update is false but the user never downloaded the crate then the
+        // first call will error; re-try with online in that case
+        let (package, manifest, crate_file) = get_package_info(&context, None)
+            .or_else(|_| get_package_info(&GlobalContext::default()?, None))
+            .or_else(|err| {
+                let ver = ver_req_to_ver(dependency);
+                if ver.is_some() {
+                    get_package_info(&GlobalContext::default()?, ver.as_ref())
+                } else {
+                    Err(err)
+                }
+            })?;
+
+        Ok(CrateInfo {
+            package,
+            manifest,
+            crate_file,
+            context,
+            source_id,
+            excludes: vec![],
+            includes: vec![],
+        })
+    }
+
+    pub fn crate_name(&self) -> &'static str {
+        self.package_id().name().as_str()
+    }
+
+    pub fn version(&self) -> &Version {
+        self.package_id().version()
+    }
+
+    pub fn semver(&self) -> String {
+        match *self.package_id().version() {
+            Version {
+                major: 0, minor, ..
+            } => format!("0.{minor}"),
+            Version { major, .. } => format!("{major}"),
+        }
+    }
+
+    pub fn manifest(&self) -> &Manifest {
+        &self.manifest
+    }
+
+    pub fn replace_manifest(&mut self, path: &Path) -> Result<&Self> {
+        if let EitherManifest::Real(v) = read_manifest(path, self.source_id, &self.context)? {
+            self.manifest = v;
+        }
+        Ok(self)
+    }
+
+    pub fn metadata(&self) -> &ManifestMetadata {
+        self.manifest.metadata()
+    }
+
+    pub fn manifest_path(&self) -> &Path {
+        self.package.manifest_path()
+    }
+
+    pub fn rust_version(&self) -> Option<String> {
+        self.manifest.rust_version().map(ToString::to_string)
+    }
+
+    pub fn targets(&self) -> &[Target] {
+        self.manifest.targets()
+    }
+
+    pub fn is_lib(&self) -> bool {
+        let mut lib = false;
+        for target in self.manifest.targets() {
+            match *target.kind() {
+                TargetKind::Lib(_) => {
+                    lib = true;
+                    break;
+                }
+                _ => continue,
+            }
+        }
+        lib
+    }
+
+    pub fn get_binary_targets(&self) -> Vec<&str> {
+        let mut bins = Vec::new();
+        for target in self.manifest.targets() {
+            match *target.kind() {
+                TargetKind::Bin => {
+                    bins.push(target.name());
+                }
+                _ => continue,
+            }
+        }
+        bins.sort_unstable();
+        bins
+    }
+
+    pub fn summary(&self) -> &Summary {
+        self.manifest.summary()
+    }
+
+    pub fn checksum(&self) -> Option<&str> {
+        self.manifest.summary().checksum()
+    }
+
+    pub fn package_id(&self) -> PackageId {
+        self.manifest.summary().package_id()
+    }
+
+    pub fn crate_file(&self) -> &FileLock {
+        &self.crate_file
+    }
+
+    pub fn dependencies(&self) -> &[Dependency] {
+        self.manifest.dependencies()
+    }
+
+    pub fn dev_dependencies(&self) -> Vec<Dependency> {
+        use cargo::core::dependency::DepKind;
+        let mut deps = vec![];
+        for dep in self.dependencies() {
+            if dep.kind() == DepKind::Development {
+                deps.push(dep.clone());
+            }
+        }
+        deps
+    }
+
+    pub fn get_summary_description(&self) -> (Option<String>, Option<String>) {
+        let (summary, description) = if let Some(ref description) = self.metadata().description {
+            // Convention these days seems to be to do manual text
+            // wrapping in crate descriptions, boo. \n\n is a real line break.
+            let mut description = description
+                .replace("\n\n", "\r")
+                .replace('\n', " ")
+                .replace('\r', "\n")
+                .trim()
+                .to_string();
+            // Trim off common prefixes
+            let re = Regex::new(&format!(
+                r"^(?i)({}|This(\s+\w+)?)(\s*,|\s+is|\s+provides)\s+",
+                self.package_id().name()
+            ))
+            .unwrap();
+            description = re.replace(&description, "").to_string();
+            let re = Regex::new(r"^(?i)(a|an|the)\s+").unwrap();
+            description = re.replace(&description, "").to_string();
+            let re =
+                Regex::new(r"^(?i)(rust\s+)?(implementation|library|tool|crate)\s+(of|to|for)\s+")
+                    .unwrap();
+            description = re.replace(&description, "").to_string();
+
+            // https://stackoverflow.com/questions/38406793/why-is-capitalizing-the-first-letter-of-a-string-so-convoluted-in-rust
+            description = {
+                let mut d = description.chars();
+                match d.next() {
+                    None => String::new(),
+                    Some(f) => f.to_uppercase().chain(d).collect::<String>(),
+                }
+            };
+
+            // Use the first sentence or first line, whichever comes first, as the summary.
+            let p1 = description.find('\n');
+            let p2 = description.find(". ");
+            match p1.into_iter().chain(p2).min() {
+                Some(p) => {
+                    let s = description[..p].trim_end_matches('.').to_string();
+                    let d = description[p + 1..].trim();
+                    if d.is_empty() {
+                        (Some(s), None)
+                    } else {
+                        (Some(s), Some(d.to_string()))
+                    }
+                }
+                None => (Some(description.trim_end_matches('.').to_string()), None),
+            }
+        } else {
+            (None, None)
+        };
+
+        (summary, description)
+    }
+
+    /// To be called before `extract_crate`.
+    pub fn set_includes_excludes(
+        &mut self,
+        excludes: Option<&Vec<String>>,
+        includes: Option<&Vec<String>>,
+    ) {
+        self.excludes = excludes.cloned().unwrap_or_default();
+        self.includes = includes.cloned().unwrap_or_default();
+    }
+
+    pub fn filter_path(&self, path: &Path) -> std::result::Result<bool, String> {
+        let top_level = path
+            .ancestors()
+            .find(|p| p.parent() == Some(Path::new("")))
+            .unwrap()
+            .to_str()
+            .ok_or_else(|| format!("Failed to get top-level element of {path:?}"))?;
+
+        let matches = move |pattern: &String| -> bool {
+            Pattern::new(&format!("{top_level}/{pattern}"))
+                .unwrap()
+                .matches_path(path)
+        };
+
+        if self.excludes.iter().any(matches) {
+            return Ok(true);
+        }
+        let suspicious = match path.extension() {
+            Some(ext) => ext == "c" || ext == "a" || ext == "S" || ext == "o" || ext == "so",
+            _ => false,
+        };
+
+        let debian_dir_pattern = Pattern::new(&format!("{top_level}/debian/*")).unwrap();
+        if debian_dir_pattern.matches_path(path) {
+            return Err(format!(
+                "Suspicious file or directory, should probably be excluded in debcargo.toml: {path:?}"
+            ));
+        }
+
+        if suspicious {
+            if self.includes.iter().any(matches) {
+                debcargo_info!("Suspicious file, on whitelist so ignored: {:?}", path);
+                Ok(false)
+            } else if testing_ignore_debpolv() {
+                debcargo_warn!("Suspicious file, ignoring as per override: {:?}", path);
+                Ok(false)
+            } else {
+                Err(format!(
+                    "Suspicious file, should probably be excluded in debcargo.toml: {path:?}"
+                ))
+            }
+        } else {
+            Ok(false)
+        }
+    }
+
+    pub fn extract_crate(&mut self, path: &Path) -> Result<(bool, bool)> {
+        let mut archive = Archive::new(GzDecoder::new(self.crate_file.file()));
+        let tempdir = tempfile::Builder::new()
+            .prefix("debcargo")
+            .tempdir_in(".")?;
+        let mut source_modified = false;
+        let mut manifest_normalized = false;
+        let mut last_mtime = 0;
+        let mut err = vec![];
+
+        for entry in archive.entries()? {
+            let mut entry = entry?;
+            match self.filter_path(&(entry.path()?)) {
+                Err(e) => err.push(e),
+                Ok(r) => {
+                    if r {
+                        source_modified = true;
+                        continue;
+                    }
+                }
+            }
+
+            if !entry.unpack_in(tempdir.path())? {
+                debcargo_bail!("Crate contained path traversals via '..'");
+            }
+
+            if let Ok(mtime) = entry.header().mtime() {
+                if mtime > last_mtime {
+                    last_mtime = mtime;
+                }
+            }
+        }
+        if !err.is_empty() {
+            for e in err {
+                debcargo_warn!("{}", e);
+            }
+            debcargo_bail!(
+                "Suspicious files detected, aborting. Ask on #debian-rust if you are stuck."
+            )
+        }
+
+        let entries = tempdir.path().read_dir()?.collect::<io::Result<Vec<_>>>()?;
+        if entries.len() != 1 || !entries[0].file_type()?.is_dir() {
+            let pkgid = self.package_id();
+            debcargo_bail!(
+                "{}-{}.crate did not unpack to a single top-level directory",
+                pkgid.name(),
+                pkgid.version()
+            );
+        }
+
+        if let Err(e) = fs::rename(entries[0].path(), path) {
+            return Err(Error::from(e).context(format!(
+                concat!(
+                    "Could not create source directory {0}\n",
+                    "To regenerate, move or remove {0}"
+                ),
+                path.display()
+            )));
+        }
+
+        // Ensure that Cargo.toml is in standard form, e.g. does not contain
+        // path dependencies, so can be built standalone (see #4030).
+        let toml_path = path.join("Cargo.toml");
+        let mut actual_toml = String::new();
+        fs::File::open(&toml_path)?.read_to_string(&mut actual_toml)?;
+
+        if !actual_toml.contains("AUTOMATICALLY GENERATED BY CARGO") {
+            // This logic should only fire for old crates, and that's what the
+            // if-conditional is supposed to check; modern versions of cargo
+            // already do this before uploading the crate, and we shouldn't need
+            // to handle it specially.
+            log::debug!("Cargo.toml not canonicalized..");
+            let orig_toml = actual_toml.clone();
+
+            // Some old uncanonicalized Cargo.toml files contain invalid relative references to
+            // license or readme files that newer cargo doesn't accept anymore. attempt to monkey
+            // patch them if possible
+            let mut check_reference = |name, value: Option<&str>| {
+                if let Some(referenced_path) = value {
+                    let full_referenced_path = path.join(referenced_path);
+                    if !full_referenced_path.exists() {
+                        debcargo_warn!(
+                            "Cargo.toml references non-existing license_file path: {:?}",
+                            full_referenced_path
+                        );
+                        if let Some((_prefix, file)) = referenced_path.rsplit_once('/') {
+                            if path.join(file).exists() {
+                                debcargo_info!("Replacing reference with '{}'", file);
+                                actual_toml = actual_toml.replace(referenced_path, file);
+                            } else {
+                                debcargo_info!("Removing reference");
+                                actual_toml = actual_toml
+                                    .replace(&format!("{name} = \"{referenced_path}\""), "");
+                            }
+                        } else {
+                            debcargo_info!("Removing reference");
+                            actual_toml =
+                                actual_toml.replace(&format!("{name} = \"{referenced_path}\""), "");
+                        }
+                        return true;
+                    }
+                }
+
+                false
+            };
+
+            if check_reference("license-file", self.metadata().license_file.as_deref())
+                || check_reference("readme", self.metadata().readme.as_deref())
+            {
+                fs::write(&toml_path, actual_toml.as_bytes())?;
+            }
+            let updated = self.replace_manifest(&toml_path.canonicalize()?)?;
+
+            let ws = Workspace::new(&toml_path.canonicalize()?, &updated.context)?;
+            let opts = PackageOpts {
+                gctx: &updated.context,
+                list: false,
+                check_metadata: false,
+                allow_dirty: true,
+                verify: false,
+                jobs: None,
+                keep_going: false,
+                to_package: Packages::Default,
+                targets: Vec::new(),
+                cli_features: CliFeatures::new_all(true),
+                reg_or_index: None,
+                dry_run: false,
+                include_lockfile: false,
+                fmt: PackageMessageFormat::Human,
+            };
+            let files = ops::package(&ws, &opts)?;
+            let file = files
+                .first()
+                .ok_or_else(|| format_err!("No canonicalized archives found.."))?;
+            let mut archive = Archive::new(GzDecoder::new(file.file()));
+
+            for entry in archive.entries()? {
+                let mut entry = entry?;
+                let entry_path = entry.path()?;
+                let mut components = entry_path.iter();
+                if components.clone().count() == 2
+                    && components.next_back() == Some(OsStr::new("Cargo.toml"))
+                {
+                    entry.unpack(&toml_path)?;
+                    break;
+                }
+            }
+            fs::write(path.join("Cargo.toml.orig"), orig_toml.as_bytes())?;
+            fs::remove_dir_all(path.join("target"))?;
+            source_modified = true;
+            manifest_normalized = true;
+            // avoid lintian errors about package-contains-ancient-file
+            // TODO: do we want to do this for unmodified tarballs? it would
+            // force us to modify them, but otherwise we get that ugly warning
+            let last_mtime = FileTime::from_unix_time(i64::try_from(last_mtime)?, 0);
+            set_file_times(toml_path, last_mtime, last_mtime)?;
+            debcargo_info!("Cargo.toml manually canonicalized!");
+        }
+        Ok((source_modified, manifest_normalized))
+    }
+}
+
+/// Collect information about the dependency structure of features and
+/// their external crate dependencies, in a simple output format.
+pub fn all_dependencies_and_features(manifest: &Manifest) -> CrateDepInfo {
+    all_dependencies_and_features_filtered(manifest, false)
+}
+
+/// Collect information about the dependency structure of features and
+/// their external crate dependencies, in a simple output format.
+/// If `include_dev_dependencies` is true, dev-dependencies will be included.
+pub fn all_dependencies_and_features_filtered(
+    manifest: &Manifest,
+    include_dev_dependencies: bool,
+) -> CrateDepInfo {
+    use cargo::core::dependency::DepKind;
+
+    let mut deps_by_name: BTreeMap<&str, Vec<&Dependency>> = BTreeMap::new();
+    for dep in manifest.dependencies() {
+        // we treat build-dependencies also as dependencies in Debian
+        if include_dev_dependencies || dep.kind() != DepKind::Development {
+            let s = dep.name_in_toml().as_str();
+            deps_by_name.entry(s).or_default().push(dep);
+        }
+    }
+    let deps_by_name = deps_by_name;
+
+    let mut features_with_deps = BTreeMap::new();
+
+    // calculate dependencies of this crate's features
+    for (feature, deps) in manifest.summary().features() {
+        let mut feature_deps: Vec<&'static str> = vec![];
+        let mut other_deps: Vec<Dependency> = Vec::new();
+        for dep in deps {
+            use self::FeatureValue::{Dep, DepFeature, Feature};
+            match dep {
+                // another feature is a dependency
+                Feature(dep_feature) => {
+                    feature_deps.push(InternedString::new(dep_feature).as_str());
+                }
+                // another package is a dependency
+                Dep { dep_name } => {
+                    // unwrap is ok, valid Cargo.toml files must have this
+                    for &dep in deps_by_name.get(dep_name.as_str()).unwrap() {
+                        other_deps.push(dep.clone());
+                    }
+                }
+                // another package is a dependency
+                DepFeature {
+                    dep_name,
+                    dep_feature,
+                    ..
+                } => {
+                    if let Some(dd) = deps_by_name.get(dep_name.as_str()) {
+                        for &dep in dd {
+                            let mut dep = dep.clone();
+                            let mut features: Vec<InternedString> =
+                                vec![InternedString::new(dep_feature)];
+                            features.extend(dep.features());
+                            dep.set_features(features);
+                            dep.set_default_features(false);
+                            other_deps.push(dep);
+                        }
+                    } else {
+                        let mut expected = false;
+                        for dep in manifest.dependencies() {
+                            if dep.kind() == DepKind::Development {
+                                let s = dep.name_in_toml().as_str();
+                                if s == dep_name.as_str() {
+                                    expected = true;
+                                }
+                            }
+                        }
+                        if expected {
+                            debcargo_warn!(
+                                "Ignoring \"{}\" feature \"{}\" as it depends on a \
+                                     dev-dependency \"{}\"",
+                                manifest.package_id(),
+                                feature,
+                                dep_name
+                            );
+                        } else {
+                            panic!(
+                                "failed to account for dependency \"{}\" of \"{}\" feature \"{}\"",
+                                dep_name,
+                                manifest.package_id(),
+                                feature
+                            );
+                        }
+                    }
+                }
+            }
+        }
+        if feature_deps.is_empty() {
+            // everything depends on bare library
+            feature_deps.push("");
+        }
+        features_with_deps.insert(feature.as_str(), (feature_deps, other_deps));
+    }
+
+    // calculate required dependencies for implicit no-default-features
+    let mut deps_required: Vec<Dependency> = Vec::new();
+    for deps in deps_by_name.values() {
+        for &dep in deps {
+            if !dep.is_optional() {
+                deps_required.push(dep.clone());
+            }
+        }
+    }
+
+    // implicit no-default-features
+    features_with_deps.insert("", (vec![], deps_required));
+
+    // implicit default feature
+    if !features_with_deps.contains_key("default") {
+        features_with_deps.insert("default", (vec![""], vec![]));
+    }
+
+    features_with_deps
+}
+
+/// Calculate all feature-dependencies and external-dependencies of a given
+/// feature, using the information previously generated by
+/// `all_dependencies_and_features`.
+pub fn transitive_deps<'a>(
+    features_with_deps: &'a CrateDepInfo,
+    feature: &str,
+) -> Result<(Vec<&'a str>, Vec<Dependency>)> {
+    let mut all_features = Vec::new();
+    let mut all_deps = Vec::new();
+    if let Some((ff, dd)) = features_with_deps.get(feature) {
+        all_features.extend(ff.clone());
+        all_deps.extend(dd.clone());
+        for f in ff {
+            let (ff1, dd1) = transitive_deps(features_with_deps, f)?;
+            all_features.extend(ff1);
+            all_deps.extend(dd1);
+        }
+    } else {
+        log::trace!("{features_with_deps:?}");
+        debcargo_bail!(
+            "requested feature '{}' not found in resolved map of features+dependencies",
+            feature
+        );
+    }
+    Ok((all_features, all_deps))
+}
diff --git a/src/deb_dependencies.rs b/src/deb_dependencies.rs
new file mode 100644 (file)
index 0000000..9171841
--- /dev/null
@@ -0,0 +1,109 @@
+use std::collections::BTreeSet;
+use std::path::{Path, PathBuf};
+
+use cargo::core::EitherManifest;
+use cargo::core::SourceId;
+use cargo::util::toml::read_manifest;
+use cargo::GlobalContext;
+
+use anyhow::Error;
+use clap::Parser;
+
+use crate::crates::all_dependencies_and_features_filtered;
+use crate::crates::transitive_deps;
+use crate::debian::deb_deps;
+use crate::debian::toolchain_deps;
+
+#[derive(Debug, Clone, Parser)]
+pub struct DebDependenciesArgs {
+    /// Cargo.toml for generating dependencies
+    cargo_toml: PathBuf,
+    /// Features to include in dependencies
+    #[clap(long)]
+    features: Vec<String>,
+    /// Include all features in dependencies
+    #[clap(long)]
+    all_features: bool,
+    /// Do not include default feature in dependencies
+    #[clap(long="no-default-features", action=clap::ArgAction::SetFalse)]
+    uses_default_features: bool,
+    /// Allow prerelease versions of dependencies
+    #[clap(long)]
+    allow_prerelease_deps: bool,
+    /// Include dev-dependencies
+    #[clap(long)]
+    include_dev_dependencies: bool,
+}
+
+/// Core function to get Debian dependencies for a Cargo.toml
+///
+/// This is the internal implementation that can be reused by multiple commands.
+pub fn get_deb_dependencies(
+    cargo_toml: &Path,
+    features: &[String],
+    all_features: bool,
+    uses_default_features: bool,
+    allow_prerelease_deps: bool,
+    include_dev_dependencies: bool,
+) -> Result<(Vec<String>, BTreeSet<String>), Error> {
+    let cargo_toml = cargo_toml.canonicalize()?;
+    let EitherManifest::Real(manifest) = read_manifest(
+        &cargo_toml,
+        SourceId::for_path(cargo_toml.parent().unwrap())?,
+        &GlobalContext::default()?,
+    )?
+    else {
+        debcargo_bail!("Manifest lacks project and package sections")
+    };
+
+    let deps_and_features =
+        all_dependencies_and_features_filtered(&manifest, include_dev_dependencies);
+
+    let feature_set = {
+        let mut feature_set: std::collections::HashSet<_> = if all_features {
+            deps_and_features.keys().copied().collect()
+        } else {
+            features
+                .iter()
+                .flat_map(|s| s.split_whitespace())
+                .flat_map(|s| s.split(','))
+                .filter(|s| !s.is_empty())
+                .collect()
+        };
+
+        if uses_default_features {
+            feature_set.insert("default");
+        }
+
+        feature_set.insert("");
+
+        feature_set
+    };
+    let dependencies = {
+        let mut dependencies = BTreeSet::<String>::new();
+        for feature in &feature_set {
+            if !deps_and_features.contains_key(feature) {
+                debcargo_bail!("Unknown feature: {}", feature);
+            }
+            let (_, feature_deps) = transitive_deps(&deps_and_features, feature)?;
+            dependencies.extend(deb_deps(allow_prerelease_deps, &feature_deps)?);
+        }
+        dependencies
+    };
+    let toolchain_deps =
+        toolchain_deps(manifest.rust_version().map(ToString::to_string).as_deref());
+    Ok((toolchain_deps, dependencies))
+}
+
+pub fn deb_dependencies(
+    args: &DebDependenciesArgs,
+) -> Result<(Vec<String>, BTreeSet<String>), Error> {
+    get_deb_dependencies(
+        &args.cargo_toml,
+        &args.features,
+        args.all_features,
+        args.uses_default_features,
+        args.allow_prerelease_deps,
+        args.include_dev_dependencies,
+    )
+}
diff --git a/src/debian/changelog.rs b/src/debian/changelog.rs
new file mode 100644 (file)
index 0000000..bf6d87d
--- /dev/null
@@ -0,0 +1,185 @@
+use anyhow;
+use chrono::{DateTime, FixedOffset, Local, TimeZone};
+use regex::Regex;
+
+use std::fmt;
+use std::str;
+
+pub const DEFAULT_DIST: &str = "UNRELEASED-FIXME-AUTOGENERATED-DEBCARGO";
+pub const COMMENT_TEAM_UPLOAD: &str = "  * Team upload.";
+
+pub struct ChangelogEntry {
+    pub source: String,
+    pub version: String,
+    pub distribution: String,
+    pub options: String,
+    pub maintainer: String,
+    pub date: DateTime<FixedOffset>,
+    pub items: Vec<String>,
+}
+
+pub fn local_now() -> DateTime<FixedOffset> {
+    let now = Local::now();
+    let offset = now
+        .timezone()
+        .offset_from_local_datetime(&now.naive_local())
+        .unwrap();
+    now.with_timezone(&offset)
+}
+
+impl fmt::Display for ChangelogEntry {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(
+            f,
+            "{} ({}) {}; {}\n",
+            self.source, self.version, self.distribution, self.options
+        )?;
+
+        for entry in &self.items {
+            writeln!(f, "{entry}")?;
+        }
+
+        writeln!(f, "\n -- {}  {}", self.maintainer, self.date.to_rfc2822())
+    }
+}
+
+fn line_is_blank(s: &str) -> bool {
+    s.chars().all(char::is_whitespace)
+}
+
+impl str::FromStr for ChangelogEntry {
+    type Err = anyhow::Error;
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let mut lines = s.lines().collect::<Vec<_>>();
+        // see https://manpages.debian.org/testing/dpkg-dev/deb-changelog.5.en.html
+        // regexes adapted from /usr/share/perl5/Dpkg/Changelog/Entry/Debian.pm
+
+        let firstline = lines[0];
+        let re1 =
+            Regex::new(r"(?i)^(\w[-+0-9a-z.]*) \(([^\(\) \t]+)\)((?:\s+[-+0-9a-z.]+)+);(.*?)\s*$")?;
+        let matches1 = re1.captures(firstline).unwrap();
+        let mut i = 1;
+        while line_is_blank(lines[i]) {
+            i += 1;
+        }
+        lines = lines.split_off(i);
+
+        while line_is_blank(lines.last().unwrap()) {
+            lines.pop();
+        }
+        let lastline = lines.pop().unwrap();
+        while line_is_blank(lines.last().unwrap()) {
+            lines.pop();
+        }
+        let re2 = Regex::new(r"^ \-\- ((?:.*) <(?:.*)>)  ?(\w.*\S)\s*$")?;
+        let matches2 = re2.captures(lastline).unwrap();
+
+        Ok(Self::new(
+            matches1[1].to_string(),
+            matches1[2].to_string(),
+            matches1[3].to_string(),
+            matches1[4].to_string(),
+            matches2[1].to_string(),
+            DateTime::parse_from_rfc2822(&matches2[2])?,
+            lines.iter().map(ToString::to_string).collect(),
+        ))
+    }
+}
+
+impl ChangelogEntry {
+    pub fn new(
+        source: String,
+        version: String,
+        distribution: String,
+        options: String,
+        maintainer: String,
+        date: DateTime<FixedOffset>,
+        items: Vec<String>,
+    ) -> Self {
+        ChangelogEntry {
+            source,
+            version,
+            distribution,
+            options,
+            maintainer,
+            date,
+            items,
+        }
+    }
+
+    pub fn maintainer_name(self: &ChangelogEntry) -> String {
+        let re = Regex::new(r"^\s*(\S.*\S)\s*<.*>\s*$").unwrap();
+        let matches = re.captures(&self.maintainer).unwrap();
+        matches[1].to_string()
+    }
+
+    pub fn version_parts(self: &ChangelogEntry) -> (String, String) {
+        let re = Regex::new(r"^(.*)-([^-]*)$").unwrap();
+        let matches = re.captures(&self.version).unwrap();
+        (matches[1].to_string(), matches[2].to_string())
+    }
+
+    pub fn deb_version_suffix(self: &ChangelogEntry) -> String {
+        let re = Regex::new(r".*-([^-]*)$").unwrap();
+        re.captures(&self.version).unwrap()[1].to_string()
+    }
+
+    pub fn deb_version_suffix_bump(self: &ChangelogEntry) -> String {
+        let suf = self.deb_version_suffix();
+        let re = Regex::new(r"^((?:.*\D)?)(\d*)$").unwrap();
+        let matches = re.captures(&suf).unwrap();
+        if matches[2].is_empty() {
+            format!("{}.1", &matches[1])
+        } else {
+            format!(
+                "{}{}",
+                &matches[1],
+                (matches[2].parse::<u64>().unwrap() + 1)
+            )
+        }
+    }
+}
+
+pub struct ChangelogIterator<'a> {
+    input: &'a [u8],
+    index: usize,
+}
+
+impl<'a> ChangelogIterator<'a> {
+    pub fn from(input: &'a str) -> ChangelogIterator<'a> {
+        ChangelogIterator {
+            input: input.as_bytes(),
+            index: 0,
+        }
+    }
+}
+
+impl<'a> Iterator for ChangelogIterator<'a> {
+    type Item = &'a str;
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a str> {
+        let slice = &self.input[self.index..];
+        if slice.is_empty() {
+            return None;
+        }
+        let mut result = slice;
+        // ghetto parser; also hack around the fact rust's str doesn't
+        // support proper indexing, boo
+        for (i, c) in slice.iter().enumerate() {
+            if *c != b'\n' {
+                continue;
+            }
+            if i < (slice.len() - 1) && (slice[i + 1] as char).is_whitespace() {
+                continue;
+            }
+            self.index += i + 1;
+            result = &slice[..=i];
+            break;
+        }
+        Some(str::from_utf8(result).unwrap())
+    }
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/debian/changelog/tests.rs b/src/debian/changelog/tests.rs
new file mode 100644 (file)
index 0000000..b244366
--- /dev/null
@@ -0,0 +1,242 @@
+use crate::debian::changelog::{ChangelogEntry, ChangelogIterator};
+use chrono::{FixedOffset, TimeZone};
+use std::str::FromStr;
+
+/// changelog for rsa selected because 0.9.2-2 appears twice
+const CHANGELOG_RSA: &str = r"rust-rsa (0.9.7-1) unstable; urgency=medium
+
+  * Team upload.
+  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5
+  * Drop unneeded dependency adjustments
+
+ -- Daniel Kahn Gillmor <dkg@fifthhorseman.net>  Thu, 05 Dec 2024 11:08:36 -0500
+
+rust-rsa (0.9.6-1) unstable; urgency=medium
+
+  * Package rsa 0.9.6 from crates.io using debcargo 2.7.0. Closes: ##1073127
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Wed, 25 Sep 2024 14:06:55 +0100
+
+rust-rsa (0.9.2-2) unstable; urgency=medium
+
+  * Add patch pkcs8: fix compatibility with pkcs8.
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Tue, 19 Sep 2023 21:27:07 +0100
+
+rust-rsa (0.9.2-2) unstable; urgency=medium
+
+  * Add patch pkcs8: fix compatibility with pkcs8.
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Tue, 19 Sep 2023 21:27:07 +0100
+
+rust-rsa (0.9.2-1) unstable; urgency=medium
+
+  * Package rsa 0.9.2 from crates.io using debcargo 2.6.0
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Mon, 18 Sep 2023 23:08:13 +0100
+
+";
+
+#[test]
+fn test_changelog_iterator() {
+    let mut iter = ChangelogIterator::from(CHANGELOG_RSA);
+
+    let section = r"rust-rsa (0.9.7-1) unstable; urgency=medium
+
+  * Team upload.
+  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5
+  * Drop unneeded dependency adjustments
+
+ -- Daniel Kahn Gillmor <dkg@fifthhorseman.net>  Thu, 05 Dec 2024 11:08:36 -0500
+
+";
+    assert_eq!(section, iter.next().unwrap());
+    let section = r"rust-rsa (0.9.6-1) unstable; urgency=medium
+
+  * Package rsa 0.9.6 from crates.io using debcargo 2.7.0. Closes: ##1073127
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Wed, 25 Sep 2024 14:06:55 +0100
+
+";
+    assert_eq!(section, iter.next().unwrap());
+    let section = r"rust-rsa (0.9.2-2) unstable; urgency=medium
+
+  * Add patch pkcs8: fix compatibility with pkcs8.
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Tue, 19 Sep 2023 21:27:07 +0100
+
+";
+    assert_eq!(section, iter.next().unwrap());
+    let section = r"rust-rsa (0.9.2-2) unstable; urgency=medium
+
+  * Add patch pkcs8: fix compatibility with pkcs8.
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Tue, 19 Sep 2023 21:27:07 +0100
+
+";
+    assert_eq!(section, iter.next().unwrap());
+    let section = r"rust-rsa (0.9.2-1) unstable; urgency=medium
+
+  * Package rsa 0.9.2 from crates.io using debcargo 2.6.0
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Mon, 18 Sep 2023 23:08:13 +0100
+
+";
+    assert_eq!(section, iter.next().unwrap());
+
+    // assert that the iterator ends
+    assert_eq!(None, iter.next());
+}
+
+#[test]
+fn test_from_string() {
+    let mut iter = ChangelogIterator::from(CHANGELOG_RSA);
+
+    let instance = ChangelogEntry::from_str(iter.next().unwrap()).unwrap();
+
+    assert_eq!("rust-rsa", instance.source);
+    assert_eq!(
+        FixedOffset::west_opt(5 * 3600)
+            .unwrap()
+            .with_ymd_and_hms(2024, 12, 05, 11, 08, 36)
+            .unwrap(),
+        instance.date
+    );
+    assert_eq!(
+        vec![
+            "  * Team upload.".to_owned(),
+            "  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5".to_owned(),
+            "  * Drop unneeded dependency adjustments".to_owned()
+        ],
+        instance.items
+    );
+    assert_eq!("0.9.7-1", instance.version);
+    assert_eq!(
+        "Daniel Kahn Gillmor <dkg@fifthhorseman.net>",
+        instance.maintainer
+    );
+    assert_eq!(" unstable", instance.distribution);
+    assert_eq!(" urgency=medium", instance.options);
+}
+
+#[test]
+fn test_changelog_entry_display() {
+    let instance = ChangelogEntry::new(
+        "rust-rsa".to_owned(),
+        "0.9.7-1".to_owned(),
+        "unstable".to_owned(),
+        "urgency=medium".to_owned(),
+        "Daniel Kahn Gillmor <dkg@fifthhorseman.net>".to_owned(),
+        FixedOffset::west_opt(5 * 3600)
+            .unwrap()
+            .with_ymd_and_hms(2024, 12, 05, 11, 08, 36)
+            .unwrap(),
+        vec![
+            "  * Team upload.".to_owned(),
+            "  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5".to_owned(),
+            "  * Drop unneeded dependency adjustments".to_owned(),
+        ],
+    );
+
+    let expected = r"rust-rsa (0.9.7-1) unstable; urgency=medium
+
+  * Team upload.
+  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5
+  * Drop unneeded dependency adjustments
+
+ -- Daniel Kahn Gillmor <dkg@fifthhorseman.net>  Thu, 5 Dec 2024 11:08:36 -0500
+";
+
+    assert_eq!(expected, instance.to_string());
+}
+
+#[test]
+fn test_changelog_entry_maintainer_name() {
+    let instance = ChangelogEntry::new(
+        "rust-rsa".to_owned(),
+        "0.9.7-1".to_owned(),
+        "unstable".to_owned(),
+        "urgency=medium".to_owned(),
+        "Daniel Kahn Gillmor <dkg@fifthhorseman.net>".to_owned(),
+        FixedOffset::west_opt(5 * 3600)
+            .unwrap()
+            .with_ymd_and_hms(2024, 12, 05, 11, 08, 36)
+            .unwrap(),
+        vec![
+            "  * Team upload.".to_owned(),
+            "  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5".to_owned(),
+            "  * Drop unneeded dependency adjustments".to_owned(),
+        ],
+    );
+
+    assert_eq!("Daniel Kahn Gillmor", instance.maintainer_name());
+}
+
+#[test]
+fn test_changelog_entry_version_parts() {
+    let instance = ChangelogEntry::new(
+        "rust-rsa".to_owned(),
+        "0.9.7-1".to_owned(),
+        "unstable".to_owned(),
+        "urgency=medium".to_owned(),
+        "Daniel Kahn Gillmor <dkg@fifthhorseman.net>".to_owned(),
+        FixedOffset::west_opt(5 * 3600)
+            .unwrap()
+            .with_ymd_and_hms(2024, 12, 05, 11, 08, 36)
+            .unwrap(),
+        vec![
+            "  * Team upload.".to_owned(),
+            "  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5".to_owned(),
+            "  * Drop unneeded dependency adjustments".to_owned(),
+        ],
+    );
+
+    assert_eq!(
+        ("0.9.7".to_owned(), "1".to_owned()),
+        instance.version_parts()
+    );
+}
+
+#[test]
+fn test_changelog_entry_deb_version_suffix() {
+    let instance = ChangelogEntry::new(
+        "rust-rsa".to_owned(),
+        "0.9.7-1".to_owned(),
+        "unstable".to_owned(),
+        "urgency=medium".to_owned(),
+        "Daniel Kahn Gillmor <dkg@fifthhorseman.net>".to_owned(),
+        FixedOffset::west_opt(5 * 3600)
+            .unwrap()
+            .with_ymd_and_hms(2024, 12, 05, 11, 08, 36)
+            .unwrap(),
+        vec![
+            "  * Team upload.".to_owned(),
+            "  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5".to_owned(),
+            "  * Drop unneeded dependency adjustments".to_owned(),
+        ],
+    );
+
+    assert_eq!("1", instance.deb_version_suffix());
+}
+
+#[test]
+fn test_changelog_entry_deb_version_suffix_bump() {
+    let instance = ChangelogEntry::new(
+        "rust-rsa".to_owned(),
+        "0.9.7-1".to_owned(),
+        "unstable".to_owned(),
+        "urgency=medium".to_owned(),
+        "Daniel Kahn Gillmor <dkg@fifthhorseman.net>".to_owned(),
+        FixedOffset::west_opt(5 * 3600)
+            .unwrap()
+            .with_ymd_and_hms(2024, 12, 05, 11, 08, 36)
+            .unwrap(),
+        vec![
+            "  * Team upload.".to_owned(),
+            "  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5".to_owned(),
+            "  * Drop unneeded dependency adjustments".to_owned(),
+        ],
+    );
+
+    assert_eq!("2", instance.deb_version_suffix_bump());
+}
diff --git a/src/debian/control.rs b/src/debian/control.rs
new file mode 100644 (file)
index 0000000..11983c9
--- /dev/null
@@ -0,0 +1,744 @@
+#[cfg(not(test))]
+use std::env::{self, VarError};
+use std::fmt::{self, Write};
+
+#[cfg(not(test))]
+use anyhow::{format_err, Error};
+use semver::Version;
+use textwrap::fill;
+
+use crate::config::{self, Config, PackageKey};
+use crate::errors::Result;
+
+/// Suffix for Rust development packages
+pub const DEV_SUFFIX: &str = "-dev";
+
+#[derive(Default, Debug)]
+pub struct BuildDeps {
+    pub(crate) build_depends: Vec<String>,
+    pub(crate) build_depends_indep: Vec<String>,
+    pub(crate) build_depends_arch: Vec<String>,
+}
+
+pub struct Source {
+    name: String,
+    version: String,
+    section: String,
+    maintainer: String,
+    uploaders: Vec<String>,
+    standards: String,
+    build_deps: BuildDeps,
+    vcs_git: String,
+    vcs_browser: String,
+    homepage: String,
+    crate_name: String,
+    requires_root: Option<String>,
+}
+
+pub struct Package {
+    name: String,
+    arch: String,
+    multi_arch: Option<String>,
+    section: Option<String>,
+    depends: Vec<String>,
+    recommends: Vec<String>,
+    suggests: Vec<String>,
+    provides: Vec<String>,
+    breaks: Vec<String>,
+    replaces: Vec<String>,
+    conflicts: Vec<String>,
+    summary: Description,
+    description: Description,
+    extra_lines: Vec<String>,
+}
+
+pub struct Description {
+    pub prefix: String,
+    pub suffix: String,
+}
+
+impl Description {
+    pub fn new(prefix: String, suffix: String) -> Self {
+        Self { prefix, suffix }
+    }
+}
+
+pub struct PkgTest {
+    name: String,
+    crate_name: String,
+    feature: String,
+    version: String,
+    extra_test_args: Vec<String>,
+    depends: Vec<String>,
+    extra_restricts: Vec<String>,
+    architecture: Vec<String>,
+}
+
+impl fmt::Display for Source {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "Source: {}", self.name)?;
+        writeln!(f, "Section: {}", self.section)?;
+        if !self.build_deps.build_depends.is_empty() {
+            writeln!(
+                f,
+                "Build-Depends: {}",
+                self.build_deps.build_depends.join(",\n ")
+            )?;
+        }
+        if !self.build_deps.build_depends_arch.is_empty() {
+            writeln!(
+                f,
+                "Build-Depends-Arch: {}",
+                self.build_deps.build_depends_arch.join(",\n ")
+            )?;
+        }
+        if !self.build_deps.build_depends_indep.is_empty() {
+            writeln!(
+                f,
+                "Build-Depends-Indep: {}",
+                self.build_deps.build_depends_indep.join(",\n ")
+            )?;
+        }
+        writeln!(f, "Maintainer: {}", self.maintainer)?;
+        if !self.uploaders.is_empty() {
+            writeln!(f, "Uploaders:\n {}", self.uploaders.join(",\n "))?;
+        }
+        writeln!(f, "Standards-Version: {}", self.standards)?;
+        writeln!(f, "Vcs-Git: {}", self.vcs_git)?;
+        writeln!(f, "Vcs-Browser: {}", self.vcs_browser)?;
+
+        if !self.homepage.is_empty() {
+            writeln!(f, "Homepage: {}", self.homepage)?;
+        }
+
+        // We used to set this conditionally, however it's best to do it
+        // unconditionally as some crates' names have a number suffix e.g.
+        // "utf-8". Without setting X-Cargo-Crate, we cannot distinguish:
+        //   a) "utf" crate at version 8 with semver_suffix = true
+        //   b) "utf-8" crate at version latest with semver_suffix = false.
+        // dh-cargo assumes (a) which is wrong for the "utf-8" crate
+        writeln!(f, "X-Cargo-Crate: {}", self.crate_name)?;
+        // Needed to get the plain upstream version for encoding it into the
+        // vendor/registry path used as install directory
+        writeln!(f, "X-Cargo-Crate-Version: {}", self.version)?;
+        if let Some(ref rrr) = self.requires_root {
+            writeln!(f, "Rules-Requires-Root: {rrr}")?;
+        }
+
+        Ok(())
+    }
+}
+
+impl fmt::Display for Package {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "Package: {}", self.name)?;
+        writeln!(f, "Architecture: {}", self.arch)?;
+        if let Some(ref multi_arch) = self.multi_arch {
+            writeln!(f, "Multi-Arch: {multi_arch}")?;
+        }
+
+        if let Some(section) = &self.section {
+            writeln!(f, "Section: {section}")?;
+        }
+
+        if !self.depends.is_empty() {
+            writeln!(f, "Depends:\n {}", self.depends.join(",\n "))?;
+        }
+        if !self.recommends.is_empty() {
+            writeln!(f, "Recommends:\n {}", self.recommends.join(",\n "))?;
+        }
+        if !self.suggests.is_empty() {
+            writeln!(f, "Suggests:\n {}", self.suggests.join(",\n "))?;
+        }
+        if !self.provides.is_empty() {
+            writeln!(f, "Provides:\n {}", self.provides.join(",\n "))?;
+        }
+        if !self.replaces.is_empty() {
+            writeln!(f, "Replaces:\n {}", self.replaces.join(",\n "))?;
+        }
+        if !self.breaks.is_empty() {
+            writeln!(f, "Breaks:\n {}", self.breaks.join(",\n "))?;
+        }
+        if !self.conflicts.is_empty() {
+            writeln!(f, "Conflicts:\n {}", self.conflicts.join(",\n "))?;
+        }
+
+        for line in &self.extra_lines {
+            writeln!(f, "{line}")?;
+        }
+
+        self.write_description(f)
+    }
+}
+
+impl fmt::Display for PkgTest {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let extra_args = if self.extra_test_args.is_empty() {
+            String::new()
+        } else {
+            format!(" {}", self.extra_test_args.join(" "))
+        };
+        writeln!(
+            f,
+            "Test-Command: /usr/share/cargo/bin/cargo-auto-test {} {} --all-targets{}",
+            self.crate_name, self.version, extra_args,
+        )?;
+        writeln!(f, "Features: test-name={}:{}", &self.name, &self.feature)?;
+        // TODO: drop the below workaround when rust-lang/cargo#5133 is fixed.
+        // The downside of our present work-around is that more dependencies
+        // must be installed, which makes it harder to actually run the tests
+        let cargo_bug_fixed = false;
+        let default_deps = if cargo_bug_fixed { &self.name } else { "@" };
+
+        let depends = if self.depends.is_empty() {
+            String::new()
+        } else {
+            format!(", {}", self.depends.join(", "))
+        };
+        writeln!(f, "Depends: dh-cargo (>= 33~){depends}, {default_deps}")?;
+
+        let restricts = if self.extra_restricts.is_empty() {
+            String::new()
+        } else {
+            format!(", {}", self.extra_restricts.join(", "))
+        };
+        writeln!(
+            f,
+            "Restrictions: allow-stderr, skip-not-installable{restricts}",
+        )?;
+        if !self.architecture.is_empty() {
+            writeln!(f, "Architecture: {}", self.architecture.join(" "))?;
+        }
+        Ok(())
+    }
+}
+
+impl Source {
+    pub fn pkg_prefix() -> &'static str {
+        if config::testing_ruzt() {
+            // avoid accidentally installing official packages during tests
+            "ruzt"
+        } else {
+            "rust"
+        }
+    }
+
+    #[allow(clippy::too_many_arguments)]
+    pub fn new(
+        basename: &str,
+        name_suffix: Option<&str>,
+        crate_name: &str,
+        crate_version: &str,
+        home: &str,
+        lib: bool,
+        maintainer: String,
+        uploaders: Vec<String>,
+        build_deps: BuildDeps,
+        requires_root: Option<String>,
+    ) -> Result<Source> {
+        let pkgbase = match name_suffix {
+            None => basename.to_string(),
+            Some(suf) => format!("{basename}{suf}"),
+        };
+        let section = if lib {
+            "rust"
+        } else {
+            "FIXME-IN-THE-SOURCE-SECTION"
+        };
+        let vcs_browser =
+            format!("https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/{pkgbase}");
+        let vcs_git =
+            format!("https://salsa.debian.org/rust-team/debcargo-conf.git [src/{pkgbase}]");
+        Ok(Source {
+            name: dsc_name(&pkgbase),
+            version: crate_version.to_string(),
+            section: section.to_string(),
+            maintainer,
+            uploaders,
+            standards: "4.7.3".to_string(),
+            build_deps,
+            vcs_git,
+            vcs_browser,
+            homepage: home.to_string(),
+            crate_name: crate_name.to_string(),
+            requires_root,
+        })
+    }
+
+    pub fn name(&self) -> &str {
+        &self.name
+    }
+
+    pub fn apply_overrides(&mut self, config: &Config) {
+        if let Some(section) = config.section() {
+            self.section = section.to_string();
+        }
+
+        if let Some(policy) = config.policy_version() {
+            self.standards = policy.to_string();
+        }
+
+        self.build_deps.build_depends.extend(
+            config
+                .build_depends()
+                .into_iter()
+                .flatten()
+                .map(String::to_string),
+        );
+        self.build_deps.build_depends_arch.extend(
+            config
+                .build_depends_arch()
+                .into_iter()
+                .flatten()
+                .map(String::to_string),
+        );
+        self.build_deps.build_depends_indep.extend(
+            config
+                .build_depends_indep()
+                .into_iter()
+                .flatten()
+                .map(String::to_string),
+        );
+        let bdeps_ex: &[String] = config.build_depends_excludes().map_or(&[], Vec::as_slice);
+        self.build_deps
+            .build_depends
+            .retain(|x| !bdeps_ex.contains(x));
+
+        self.build_deps
+            .build_depends_arch
+            .retain(|x| !bdeps_ex.contains(x));
+
+        self.build_deps
+            .build_depends_indep
+            .retain(|x| !bdeps_ex.contains(x));
+
+        if let Some(homepage) = config.homepage() {
+            self.homepage = homepage.to_string();
+        }
+
+        if let Some(vcs_git) = config.vcs_git() {
+            self.vcs_git = vcs_git.to_string();
+        }
+
+        if let Some(vcs_browser) = config.vcs_browser() {
+            self.vcs_browser = vcs_browser.to_string();
+        }
+    }
+}
+
+impl Package {
+    pub fn pkg_prefix() -> &'static str {
+        if config::testing_ruzt() {
+            // avoid accidentally installing official packages during tests
+            "libruzt"
+        } else {
+            "librust"
+        }
+    }
+
+    fn deb_feature2(p: &str, f: &str) -> String {
+        format!(
+            "{} (= ${{binary:Version}})",
+            match f {
+                "" => deb_name(p),
+                _ => deb_feature_name(p, f),
+            }
+        )
+    }
+    fn deb_feature(f: &str, pkgbase: &str) -> String {
+        Package::deb_feature2(pkgbase, f)
+    }
+
+    fn filter_provides(x: &[&str], f_provides: &[&str], pkgbase: &str) -> Vec<String> {
+        x.iter()
+            .filter(|f| !f_provides.contains(f))
+            .map(|f| Package::deb_feature(f, pkgbase))
+            .collect()
+    }
+
+    #[allow(clippy::too_many_arguments)]
+    pub fn new(
+        basename: &str,
+        name_suffix: Option<&str>,
+        version: &Version,
+        summary: Description,
+        description: Description,
+        feature: Option<&str>,
+        f_deps: &[&str],
+        o_deps: Vec<String>,
+        f_provides: &[&str],
+        f_recommends: &[&str],
+        f_suggests: &[&str],
+    ) -> Result<Package> {
+        let pkgbase = match name_suffix {
+            None => basename.to_string(),
+            Some(suf) => format!("{basename}{suf}"),
+        };
+        let (recommends, suggests) = match feature {
+            Some(_) => (vec![], vec![]),
+            None => (
+                Package::filter_provides(f_recommends, f_provides, &pkgbase),
+                Package::filter_provides(f_suggests, f_provides, &pkgbase),
+            ),
+        };
+
+        // Provides for all possible versions, see:
+        // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=901827#35
+        // https://wiki.debian.org/Teams/RustPackaging/Policy#Package_provides
+        let mut provides = vec![];
+        let version_suffixes = [
+            String::new(),
+            format!("-{}", version.major),
+            format!("-{}.{}", version.major, version.minor),
+            format!("-{}.{}.{}", version.major, version.minor, version.patch),
+        ];
+        for suffix in &version_suffixes {
+            // don't provide unversioned variants in semver-suffix packages
+            if name_suffix.is_some() && suffix.is_empty() {
+                continue;
+            }
+
+            let p = format!("{basename}{suffix}");
+            provides.push(Package::deb_feature2(&p, feature.unwrap_or("")));
+            provides.extend(f_provides.iter().map(|f| Package::deb_feature2(&p, f)));
+        }
+        let provides_self = Package::deb_feature(feature.unwrap_or(""), &pkgbase);
+        // rust dropped Vec::remove_item for annoying reasons, the below is
+        // an unofficialy recommended replacement from the RFC #40062
+        let i = provides.iter().position(|x| *x == *provides_self);
+        i.map(|i| provides.remove(i));
+
+        let mut depends = vec!["${misc:Depends}".to_string()];
+        if feature.is_some() && !f_deps.contains(&"") {
+            // in dh-cargo we symlink /usr/share/doc/{$feature => $main} pkg
+            // so we always need this direct dependency, even if the feature
+            // only indirectly depends on the bare library via another
+            depends.push(Package::deb_feature("", &pkgbase));
+        }
+        depends.extend(f_deps.iter().map(|f| Package::deb_feature(f, &pkgbase)));
+        depends.extend(o_deps);
+        let mut breaks = vec![];
+        let mut replaces = vec![];
+        if name_suffix.is_some() && feature.is_none() {
+            // B+R needs to be set on "real" package, not virtual ones
+            // constrain by "next" version, so that it is possible to install a newer,
+            // non-suffixed package at the same time
+            let mut next_version = version.clone();
+            next_version.patch += 1;
+            breaks.push(format!("{} (<< {}~)", deb_name(basename), next_version));
+            replaces.push(format!("{} (<< {}~)", deb_name(basename), next_version));
+        }
+        let conflicts = vec![];
+
+        Ok(Package {
+            name: match feature {
+                None => deb_name(&pkgbase),
+                Some(f) => deb_feature_name(&pkgbase, f),
+            },
+            arch: "any".to_string(),
+            // This is the best but not ideal option for us.
+            //
+            // Currently Debian M-A spec has a deficiency where a package X that
+            // build-depends on a (M-A:foreign+arch:all) package that itself
+            // depends on an arch:any package Z, will pick up the BUILD_ARCH of
+            // package Z instead of the HOST_ARCH. This is because we currently
+            // have no way of telling dpkg to use HOST_ARCH when checking that the
+            // dependencies of Y are satisfied, which is done at install-time
+            // without any knowledge that we're about to do a cross-compile. It
+            // is also problematic to tell dpkg to "accept any arch" because of
+            // the presence of non-M-A:same packages in the archive, that are not
+            // co-installable - different arches of Z might be depended-upon by
+            // two conflicting chains. (dpkg has so far chosen not to add an
+            // exception for the case where package Z is M-A:same co-installable).
+            //
+            // The recommended work-around for now from the dpkg developers is to
+            // make our packages arch:any M-A:same even though this results in
+            // duplicate packages in the Debian archive. For very large crates we
+            // will eventually want to make debcargo generate -data packages that
+            // are arch:all and have the arch:any -dev packages depend on it.
+            multi_arch: Some("same".to_string()),
+            section: None,
+            depends,
+            recommends,
+            suggests,
+            provides,
+            breaks,
+            replaces,
+            conflicts,
+            summary,
+            description,
+            extra_lines: vec![],
+        })
+    }
+
+    pub fn new_bin(
+        basename: &str,
+        name_suffix: Option<&str>,
+        section: Option<&str>,
+        summary: Description,
+        description: Description,
+    ) -> Self {
+        let (name, mut provides) = match name_suffix {
+            None => (basename.to_string(), vec![]),
+            Some(suf) => (
+                format!("{basename}{suf}"),
+                vec![format!("{} (= ${{binary:Version}})", basename)],
+            ),
+        };
+        provides.push("${cargo:Provides}".to_string());
+        Package {
+            name,
+            arch: "any".to_string(),
+            multi_arch: None,
+            section: section.map(ToString::to_string),
+            depends: vec![
+                "${misc:Depends}".to_string(),
+                "${shlibs:Depends}".to_string(),
+                "${cargo:Depends}".to_string(),
+            ],
+            recommends: vec!["${cargo:Recommends}".to_string()],
+            suggests: vec!["${cargo:Suggests}".to_string()],
+            provides,
+            breaks: vec![],
+            replaces: vec![],
+            conflicts: vec![],
+            summary,
+            description,
+            extra_lines: vec![
+                "Built-Using: ${cargo:Built-Using}".to_string(),
+                "Static-Built-Using: ${cargo:Static-Built-Using}".to_string(),
+            ],
+        }
+    }
+
+    pub fn new_extra(name: String) -> Self {
+        Package {
+            name,
+            arch: String::default(),
+            multi_arch: Option::default(),
+            section: Option::default(),
+            depends: Vec::default(),
+            recommends: Vec::default(),
+            suggests: Vec::default(),
+            provides: Vec::default(),
+            breaks: Vec::default(),
+            replaces: Vec::default(),
+            conflicts: Vec::default(),
+            summary: Description::new(String::default(), String::default()),
+            description: Description::new(String::default(), String::default()),
+            extra_lines: Vec::default(),
+        }
+    }
+
+    pub fn name(&self) -> &str {
+        self.name.as_str()
+    }
+
+    fn write_description(&self, out: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(out, "Description: {}", &self.summary)?;
+        let description = format!("{}", &self.description);
+        for line in fill(description.trim(), 79).lines() {
+            let line = line.trim_end();
+            if line.is_empty() {
+                writeln!(out, " .")?;
+            } else if line.starts_with("- ") {
+                writeln!(out, "  {line}")?;
+            } else {
+                writeln!(out, " {line}")?;
+            }
+        }
+        Ok(())
+    }
+
+    #[allow(clippy::result_unit_err)]
+    pub fn summary_check_len(&self) -> std::result::Result<(), ()> {
+        if self.summary.prefix.len() <= 80 {
+            Ok(())
+        } else {
+            Err(())
+        }
+    }
+
+    pub fn apply_overrides(&mut self, config: &Config, key: PackageKey, f_provides: &[&str]) {
+        if let Some(section) = config.package_section(key) {
+            self.section = Some(section.to_string());
+        }
+        self.summary
+            .apply_overrides(config.summary.as_deref(), config.package_summary(key));
+        self.description.apply_overrides(
+            config.description.as_deref(),
+            config.package_description(key),
+        );
+
+        self.depends.extend(config::package_field_for_feature(
+            |x| config.package_depends(x),
+            key,
+            f_provides,
+        ));
+        self.recommends.extend(config::package_field_for_feature(
+            |x| config.package_recommends(x),
+            key,
+            f_provides,
+        ));
+        self.suggests.extend(config::package_field_for_feature(
+            |x| config.package_suggests(x),
+            key,
+            f_provides,
+        ));
+        self.provides.extend(config::package_field_for_feature(
+            |x| config.package_provides(x),
+            key,
+            f_provides,
+        ));
+        self.breaks.extend(config::package_field_for_feature(
+            |x| config.package_breaks(x),
+            key,
+            f_provides,
+        ));
+        self.replaces.extend(config::package_field_for_feature(
+            |x| config.package_replaces(x),
+            key,
+            f_provides,
+        ));
+        self.conflicts.extend(config::package_field_for_feature(
+            |x| config.package_conflicts(x),
+            key,
+            f_provides,
+        ));
+        self.extra_lines.extend(
+            config
+                .package_extra_lines(key)
+                .into_iter()
+                .flatten()
+                .map(ToString::to_string),
+        );
+        if let Some(architecture) = config.package_architecture(key) {
+            self.arch = architecture.join(" ");
+        }
+        if let Some(multi_arch) = config.package_multi_arch(key) {
+            self.multi_arch = Some(multi_arch.to_owned());
+        }
+    }
+}
+
+impl Description {
+    fn apply_overrides(&mut self, global: Option<&str>, per_package: Option<&str>) {
+        if let Some(per_package) = per_package {
+            self.prefix = per_package.to_string();
+            self.suffix = String::new();
+        } else if let Some(global) = global {
+            self.prefix = global.to_owned();
+        }
+    }
+}
+impl fmt::Display for Description {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}{}", &self.prefix, self.suffix)
+    }
+}
+
+impl PkgTest {
+    #[allow(clippy::too_many_arguments)]
+    pub fn new(
+        name: &str,
+        crate_name: &str,
+        feature: &str,
+        version: &str,
+        extra_test_args: &[&str],
+        depends: &[String],
+        extra_restricts: &[&str],
+        architecture: &[&str],
+    ) -> Result<PkgTest> {
+        Ok(PkgTest {
+            name: name.to_string(),
+            crate_name: crate_name.to_string(),
+            feature: feature.to_string(),
+            version: version.to_string(),
+            extra_test_args: extra_test_args.iter().map(ToString::to_string).collect(),
+            depends: depends.to_vec(),
+            extra_restricts: extra_restricts.iter().map(ToString::to_string).collect(),
+            architecture: architecture.iter().map(ToString::to_string).collect(),
+        })
+    }
+}
+
+/// Translates a semver into a Debian-format upstream version.
+/// Omits the build metadata, and uses a ~ before the prerelease version so it
+/// compares earlier than the subsequent release.
+pub fn deb_upstream_version(v: &Version, repack: Option<&str>) -> String {
+    let mut s = format!("{}.{}.{}", v.major, v.minor, v.patch);
+    if !v.pre.is_empty() {
+        write!(s, "~{}", v.pre.as_str()).unwrap();
+    }
+    if let Some(repack_suffix) = repack {
+        write!(s, "+{repack_suffix}").unwrap();
+    }
+    s
+}
+
+pub fn base_deb_name(crate_name: &str) -> String {
+    crate_name.replace('_', "-").to_lowercase()
+}
+
+pub fn dsc_name(name: &str) -> String {
+    format!("{}-{}", Source::pkg_prefix(), base_deb_name(name))
+}
+
+pub fn deb_name(name: &str) -> String {
+    format!(
+        "{}-{}{}",
+        Package::pkg_prefix(),
+        base_deb_name(name),
+        DEV_SUFFIX
+    )
+}
+
+pub fn deb_feature_name(name: &str, feature: &str) -> String {
+    format!(
+        "{}-{}+{}{}",
+        Package::pkg_prefix(),
+        base_deb_name(name),
+        base_deb_name(feature),
+        DEV_SUFFIX
+    )
+}
+
+/// Retrieve one of a series of environment variables, and provide a friendly error message for
+/// non-UTF-8 values.
+#[cfg(not(test))]
+fn get_envs(keys: &[&str]) -> Result<Option<String>> {
+    for key in keys {
+        match env::var(key) {
+            Ok(val) => {
+                return Ok(Some(val));
+            }
+            Err(e @ VarError::NotUnicode(_)) => {
+                return Err(
+                    Error::from(e).context(format!("Environment variable ${key} not valid UTF-8"))
+                );
+            }
+            Err(VarError::NotPresent) => {}
+        }
+    }
+    Ok(None)
+}
+
+#[cfg(test)]
+pub(crate) fn get_deb_author() -> Result<String> {
+    Ok("Debcargo Test <debcargo@example.com>".to_string())
+}
+
+/// Determine a name and email address from environment variables.
+#[cfg(not(test))]
+pub fn get_deb_author() -> Result<String> {
+    let name = get_envs(&["DEBFULLNAME", "NAME"])?.ok_or_else(|| {
+        format_err!("Unable to determine your name; please set $DEBFULLNAME or $NAME")
+    })?;
+    let email = get_envs(&["DEBEMAIL", "EMAIL"])?.ok_or_else(|| {
+        format_err!("Unable to determine your email; please set $DEBEMAIL or $EMAIL")
+    })?;
+    Ok(format!("{name} <{email}>"))
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/debian/control/tests.rs b/src/debian/control/tests.rs
new file mode 100644 (file)
index 0000000..7d04dd3
--- /dev/null
@@ -0,0 +1,419 @@
+use super::{
+    base_deb_name, deb_feature_name, deb_name, deb_upstream_version, dsc_name, Description,
+    Package, PkgTest, Source,
+};
+use crate::{
+    config::{Config, SourceOverride},
+    debian::BuildDeps,
+};
+use semver::{Prerelease, Version};
+
+#[test]
+fn source_to_string() {
+    let instance = Source::new(
+        "rsa",
+        None,
+        "rsa",
+        "1.2.3",
+        "https://github.com/RustCrypto/RSA",
+        true,
+        "Jelmer Vernooij <jelmer@debian.org>".to_owned(),
+        vec!["Jelmer Vernooij <jelmer@debian.org>".to_owned()],
+        BuildDeps::default(),
+        None,
+    )
+    .unwrap();
+
+    let expected = "Source: rust-rsa\nSection: rust\nMaintainer: Jelmer Vernooij <jelmer@debian.org>\nUploaders:\n Jelmer Vernooij <jelmer@debian.org>\nStandards-Version: 4.7.3\nVcs-Git: https://salsa.debian.org/rust-team/debcargo-conf.git [src/rsa]\nVcs-Browser: https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/rsa\nHomepage: https://github.com/RustCrypto/RSA\nX-Cargo-Crate: rsa\nX-Cargo-Crate-Version: 1.2.3\n";
+
+    assert_eq!(expected, instance.to_string());
+}
+
+fn empty_source_overrides() -> SourceOverride {
+    SourceOverride::new(
+        Some("".to_owned()),
+        Some("".to_owned()),
+        Some("".to_owned()),
+        Some("".to_owned()),
+        Some("".to_owned()),
+        Some(vec!["rust-digest".to_owned()]),
+        Some(vec!["".to_owned()]),
+        Some(vec!["".to_owned()]),
+        Some(vec!["rust-const-oid".to_owned()]),
+        Some(false),
+    )
+}
+
+#[test]
+fn test_description_display() {
+    let instance = Description::new("prefix".to_owned(), "suffix".to_owned());
+
+    assert_eq!("prefixsuffix", instance.to_string())
+}
+
+#[test]
+fn test_apply_overrides() {
+    let mut instance = Source::new(
+        "rsa",
+        None,
+        "rsa",
+        "5.1.2",
+        "https://github.com/RustCrypto/RSA",
+        true,
+        "Jelmer Vernooij <jelmer@debian.org>".to_owned(),
+        vec!["Jelmer Vernooij <jelmer@debian.org>".to_owned()],
+        BuildDeps {
+            build_depends: vec![
+                "rust-const-oid".to_owned(),
+                "rust-num-bigint-dig".to_owned(),
+            ],
+            ..BuildDeps::default()
+        },
+        Some("no".to_owned()),
+    )
+    .unwrap();
+
+    assert_eq!("rust", instance.section);
+    assert_eq!(
+        vec!["rust-const-oid", "rust-num-bigint-dig"],
+        instance.build_deps.build_depends
+    );
+    assert_eq!("https://github.com/RustCrypto/RSA", instance.homepage);
+    assert_eq!(
+        "https://salsa.debian.org/rust-team/debcargo-conf.git [src/rsa]",
+        instance.vcs_git
+    );
+    assert_eq!(
+        "https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/rsa",
+        instance.vcs_browser
+    );
+
+    let mut config = Config::default();
+    config.source = Some(empty_source_overrides());
+    instance.apply_overrides(&config);
+
+    assert_eq!("", instance.section);
+    assert_eq!(
+        vec!["rust-num-bigint-dig", "rust-digest"],
+        instance.build_deps.build_depends
+    );
+    assert_eq!("", instance.homepage);
+    assert_eq!("", instance.vcs_git);
+    assert_eq!("", instance.vcs_browser);
+}
+
+#[test]
+fn test_package_new() {
+    let basename: &str = "rsa";
+    let name_suffix: Option<&str> = None;
+    let version: &Version = &Version {
+        major: 0,
+        minor: 9,
+        patch: 7,
+        pre: Default::default(),
+        build: Default::default(),
+    };
+    let summary: Description = Description::new("summary_pre".to_owned(), "summary_suf".to_owned());
+    let description: Description =
+        Description::new("description_pre".to_owned(), "description_suf".to_owned());
+    let feature: Option<&str> = None;
+    let f_deps: Vec<&str> = vec![];
+    let o_deps: Vec<String> = vec![];
+    let f_provides: Vec<&str> = vec![];
+    let f_recommends: Vec<&str> = vec![];
+    let f_suggests: Vec<&str> = vec![];
+    let instance = Package::new(
+        basename,
+        name_suffix,
+        version,
+        summary,
+        description,
+        feature,
+        &f_deps,
+        o_deps,
+        &f_provides,
+        &f_recommends,
+        &f_suggests,
+    );
+
+    assert!(instance.is_ok());
+    let instance = instance.unwrap();
+    assert_eq!("any", instance.arch);
+    assert_eq!(Some("same".to_string()), instance.multi_arch);
+    assert_eq!(None, instance.section);
+    assert_eq!(vec!["${misc:Depends}"], instance.depends);
+    assert_eq!(Vec::<String>::new(), instance.recommends);
+    assert_eq!(Vec::<String>::new(), instance.suggests);
+    assert_eq!(
+        vec![
+            "librust-rsa-0-dev (= ${binary:Version})",
+            "librust-rsa-0.9-dev (= ${binary:Version})",
+            "librust-rsa-0.9.7-dev (= ${binary:Version})"
+        ],
+        instance.provides
+    );
+    assert_eq!("summary_pre", instance.summary.prefix);
+    assert_eq!("summary_suf", instance.summary.suffix);
+    assert_eq!("description_pre", instance.description.prefix);
+    assert_eq!("description_suf", instance.description.suffix);
+    assert_eq!(Vec::<String>::new(), instance.extra_lines);
+}
+
+#[test]
+fn test_package_new_bin() {
+    let basename: &str = "rsa";
+    let name_suffix: Option<&str> = None;
+    let section = Some("rust");
+    let summary: Description = Description::new("summary_pre".to_owned(), "summary_suf".to_owned());
+    let description: Description =
+        Description::new("description_pre".to_owned(), "description_suf".to_owned());
+    let instance = Package::new_bin(basename, name_suffix, section, summary, description);
+
+    assert_eq!("any", instance.arch);
+    assert_eq!(None, instance.multi_arch);
+    assert_eq!(Some("rust".to_owned()), instance.section);
+    assert_eq!(
+        vec!["${misc:Depends}", "${shlibs:Depends}", "${cargo:Depends}"],
+        instance.depends
+    );
+    assert_eq!(vec!["${cargo:Recommends}"], instance.recommends);
+    assert_eq!(vec!["${cargo:Suggests}"], instance.suggests);
+    assert_eq!(vec!["${cargo:Provides}"], instance.provides);
+    assert_eq!("summary_pre", instance.summary.prefix);
+    assert_eq!("summary_suf", instance.summary.suffix);
+    assert_eq!("description_pre", instance.description.prefix);
+    assert_eq!("description_suf", instance.description.suffix);
+    assert_eq!(
+        vec![
+            "Built-Using: ${cargo:Built-Using}",
+            "Static-Built-Using: ${cargo:Static-Built-Using}"
+        ],
+        instance.extra_lines
+    );
+}
+
+#[test]
+fn test_package_display() {
+    let basename: &str = "rsa";
+    let name_suffix: Option<&str> = None;
+    let section = Some("rust");
+    let summary: Description = Description::new("".to_owned(), "".to_owned());
+    let description: Description = Description::new(
+        "description_start\n\nempty lines\n\ndescription_stop".to_owned(),
+        "".to_owned(),
+    );
+    let instance = Package::new_bin(basename, name_suffix, section, summary, description);
+
+    let expected = "Package: rsa\nArchitecture: any\nSection: rust\nDepends:\n ${misc:Depends},\n ${shlibs:Depends},\n ${cargo:Depends}\nRecommends:\n ${cargo:Recommends}\nSuggests:\n ${cargo:Suggests}\nProvides:\n ${cargo:Provides}\nBuilt-Using: ${cargo:Built-Using}\nStatic-Built-Using: ${cargo:Static-Built-Using}\nDescription: \n description_start\n .\n empty lines\n .\n description_stop\n";
+
+    assert_eq!(expected, instance.to_string());
+}
+
+#[test]
+fn test_package_display_arch() {
+    let basename: &str = "tiny-dfr";
+    let name_suffix: Option<&str> = None;
+    let section = Some("utils");
+    let summary: Description = Description::new("".to_owned(), "".to_owned());
+    let description: Description = Description::new(
+        "description_start\n\nempty lines\n\ndescription_stop".to_owned(),
+        "".to_owned(),
+    );
+    let mut instance = Package::new_bin(basename, name_suffix, section, summary, description);
+    instance.arch = "arm64 amd64".to_string();
+
+    let expected = "Package: tiny-dfr\nArchitecture: arm64 amd64\nSection: utils\nDepends:\n ${misc:Depends},\n ${shlibs:Depends},\n ${cargo:Depends}\nRecommends:\n ${cargo:Recommends}\nSuggests:\n ${cargo:Suggests}\nProvides:\n ${cargo:Provides}\nBuilt-Using: ${cargo:Built-Using}\nStatic-Built-Using: ${cargo:Static-Built-Using}\nDescription: \n description_start\n .\n empty lines\n .\n description_stop\n";
+
+    assert_eq!(expected, instance.to_string());
+}
+
+#[test]
+fn test_package_summary_check_len() {
+    let basename: &str = "rsa";
+    let name_suffix: Option<&str> = None;
+    let section = Some("rust");
+    let summary: Description = Description::new("".to_owned(), "".to_owned());
+    let description: Description = Description::new(
+        "description_start\n\nempty lines\n\ndescription_stop".to_owned(),
+        "".to_owned(),
+    );
+    let instance = Package::new_bin(basename, name_suffix, section, summary, description);
+
+    assert!(instance.summary_check_len().is_ok());
+}
+
+#[test]
+fn test_package_summary_check_len_err() {
+    let basename: &str = "rsa";
+    let name_suffix: Option<&str> = None;
+    let section = Some("rust");
+    // 81 character long line
+    let summary: Description = Description::new(
+        "123456789012345678901234567890123456789012345678901234567890123456789012345678901"
+            .to_owned(),
+        "".to_owned(),
+    );
+    let description: Description = Description::new(
+        "description_start\n\nempty lines\n\ndescription_stop".to_owned(),
+        "".to_owned(),
+    );
+    let instance = Package::new_bin(basename, name_suffix, section, summary, description);
+
+    assert!(instance.summary_check_len().is_err());
+}
+
+#[test]
+fn test_pkg_test_new() {
+    let name = "rsa";
+    let crate_name = "rsa";
+    let feature = "pem";
+    let version = "0.9.7";
+    let extra_test_args: Vec<&str> = vec![];
+    let depends: Vec<String> = vec![];
+    let extra_restricts: Vec<&str> = vec![];
+    let architecture: Vec<&str> = vec![];
+    let instance = PkgTest::new(
+        name,
+        crate_name,
+        feature,
+        version,
+        &extra_test_args,
+        &depends,
+        &extra_restricts,
+        &architecture,
+    );
+
+    assert!(instance.is_ok());
+    let instance = instance.unwrap();
+    assert_eq!("rsa", instance.name);
+    assert_eq!("rsa", instance.crate_name);
+    assert_eq!("pem", instance.feature);
+    assert_eq!("0.9.7", instance.version);
+    assert_eq!(Vec::<String>::new(), instance.extra_test_args);
+    assert_eq!(Vec::<String>::new(), instance.depends);
+    assert_eq!(Vec::<String>::new(), instance.extra_restricts);
+    assert_eq!(Vec::<String>::new(), instance.architecture);
+}
+
+#[test]
+fn test_deb_upstream_version_without_pre() {
+    let version = Version {
+        major: 0,
+        minor: 9,
+        patch: 7,
+        pre: Default::default(),
+        build: Default::default(),
+    };
+
+    let result = deb_upstream_version(&version, None);
+
+    let expected = "0.9.7";
+
+    assert_eq!(expected, result);
+
+    let result = deb_upstream_version(&version, Some("dfsg9"));
+
+    let expected = "0.9.7+dfsg9";
+
+    assert_eq!(expected, result);
+}
+
+#[test]
+fn test_deb_upstream_version_with_pre() {
+    let version = Version {
+        major: 0,
+        minor: 9,
+        patch: 7,
+        pre: Prerelease::new("alpha").unwrap(),
+        build: Default::default(),
+    };
+
+    let result = deb_upstream_version(&version, Some("dfsg9"));
+
+    let expected = "0.9.7~alpha+dfsg9";
+
+    assert_eq!(expected, result);
+}
+
+#[test]
+fn test_base_deb_name() {
+    let result = base_deb_name("derive_more");
+
+    let expected = "derive-more";
+
+    assert_eq!(expected, result);
+}
+
+#[test]
+fn test_dsc_name() {
+    let result = dsc_name("derive_more");
+
+    let expected = "rust-derive-more";
+
+    assert_eq!(expected, result);
+}
+
+#[test]
+fn test_deb_name() {
+    let result = deb_name("derive_more");
+
+    let expected = "librust-derive-more-dev";
+
+    assert_eq!(expected, result);
+}
+
+#[test]
+fn test_deb_feature_name() {
+    let result = deb_feature_name("derive_more", "add");
+
+    let expected = "librust-derive-more+add-dev";
+
+    assert_eq!(expected, result);
+}
+
+struct PkgTestFmtData<'a> {
+    feature: &'a str,
+    extra_test_args: Vec<&'a str>,
+    depends: Vec<String>,
+    extra_restricts: Vec<&'a str>,
+    architecture: &'a [&'a str],
+}
+
+#[test]
+fn pkgtest_fmt_has_no_extra_whitespace() {
+    let checks = vec![
+        PkgTestFmtData {
+            feature: "",
+            extra_test_args: Vec::new(),
+            depends: Vec::new(),
+            extra_restricts: Vec::new(),
+            architecture: &[],
+        },
+        PkgTestFmtData {
+            feature: "X",
+            extra_test_args: vec!["--no-default-features", "--features X"],
+            depends: vec!["libfoo-dev".into(), "bar".into()],
+            extra_restricts: vec!["flaky"],
+            architecture: &["!riscv64"],
+        },
+    ];
+
+    for check in checks {
+        let pkgtest = PkgTest::new(
+            "librust-crate-dev",
+            "crate",
+            check.feature,
+            "1.0",
+            &check.extra_test_args,
+            &check.depends,
+            &check.extra_restricts,
+            check.architecture,
+        )
+        .unwrap();
+
+        for ln in pkgtest.to_string().lines() {
+            let trimmed = ln.trim_end();
+            assert_eq!(trimmed, ln);
+        }
+    }
+}
diff --git a/src/debian/copyright.rs b/src/debian/copyright.rs
new file mode 100644 (file)
index 0000000..ea7dca9
--- /dev/null
@@ -0,0 +1,454 @@
+use cargo::core::manifest;
+use chrono::{DateTime, Datelike};
+use git2::Repository;
+use regex;
+use tempfile;
+use textwrap::fill;
+use walkdir;
+
+use std::cmp::Ordering;
+use std::collections::BTreeMap;
+use std::env;
+use std::fmt;
+use std::fs;
+use std::io::{BufRead, BufReader, Read};
+use std::path::Path;
+
+use crate::errors::Result;
+
+const DEB_COPYRIGHT_FORMAT: &str = "\
+     https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/";
+
+macro_rules! format_para {
+    ($fmt: expr, $text:expr) => {{
+        for line in $text.lines() {
+            let line = line.trim_end();
+            if line.is_empty() {
+                writeln!($fmt, " .")?;
+            } else {
+                writeln!($fmt, " {}", line)?;
+            }
+        }
+        write!($fmt, "")
+    }};
+}
+
+struct UpstreamInfo {
+    name: String,
+    contacts: Vec<String>,
+    source: String,
+}
+
+#[derive(Clone)]
+pub struct Files {
+    files: String,
+    copyright: Vec<String>,
+    license: String,
+    comment: String,
+}
+
+#[derive(Clone)]
+struct License {
+    name: String,
+    text: String,
+}
+
+pub struct DebCopyright {
+    format: String,
+    upstream: UpstreamInfo,
+    files: Vec<Files>,
+    licenses: Vec<License>,
+    exclusions: Vec<String>,
+}
+
+impl fmt::Display for DebCopyright {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "Format: {}", self.format)?;
+        write!(f, "{}", self.upstream)?;
+        if !self.exclusions.is_empty() {
+            write!(f, "Files-Excluded:")?;
+            for excluded in &self.exclusions {
+                write!(f, "\n {excluded}")?;
+            }
+            writeln!(f)?;
+        }
+
+        for file in &self.files {
+            write!(f, "\n{file}")?;
+        }
+
+        for license in &self.licenses {
+            write!(f, "\n{license}")?;
+        }
+
+        Ok(())
+    }
+}
+
+impl DebCopyright {
+    fn new(u: UpstreamInfo, f: &[Files], l: &[License], e: &[String]) -> DebCopyright {
+        DebCopyright {
+            format: DEB_COPYRIGHT_FORMAT.to_string(),
+            upstream: u,
+            files: f.to_vec(),
+            licenses: l.to_vec(),
+            exclusions: e.to_vec(),
+        }
+    }
+}
+
+impl fmt::Display for UpstreamInfo {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "Upstream-Name: {}", self.name)?;
+        write!(f, "Upstream-Contact:")?;
+        if self.contacts.len() > 1 {
+            writeln!(f)?;
+        }
+        for contact in &self.contacts {
+            writeln!(f, " {contact}")?;
+        }
+        if !self.source.is_empty() {
+            writeln!(f, "Source: {}", self.source)?;
+        }
+
+        Ok(())
+    }
+}
+
+impl UpstreamInfo {
+    fn new(name: String, authors: &[String], repo: &str) -> UpstreamInfo {
+        assert!(!authors.is_empty());
+        UpstreamInfo {
+            name,
+            contacts: authors.to_vec(),
+            source: repo.to_string(),
+        }
+    }
+}
+
+impl fmt::Display for Files {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "Files: {}", self.files)?;
+        write!(f, "Copyright:")?;
+        if self.copyright.len() > 1 {
+            writeln!(f)?;
+        }
+        for copyright in &self.copyright {
+            writeln!(f, " {copyright}")?;
+        }
+        writeln!(f, "License: {}", self.license)?;
+        if !self.comment.is_empty() {
+            writeln!(f, "Comment:")?;
+            format_para!(f, &self.comment)?;
+        }
+        Ok(())
+    }
+}
+
+impl Files {
+    pub fn new<T: ToString>(name: &str, notice: &[T], license: &str, comment: &str) -> Files {
+        assert!(!notice.is_empty());
+        Files {
+            files: name.to_string(),
+            copyright: notice.iter().map(ToString::to_string).collect(),
+            license: license.to_string(),
+            comment: comment.to_string(),
+        }
+    }
+
+    pub fn files(&self) -> &str {
+        &self.files
+    }
+
+    pub fn license(&self) -> &str {
+        &self.license
+    }
+}
+
+impl fmt::Display for License {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "License: {}", self.name)?;
+        format_para!(f, &self.text)?;
+        Ok(())
+    }
+}
+
+impl License {
+    fn new(name: String, text: String) -> License {
+        License { name, text }
+    }
+}
+
+macro_rules! default_files {
+    ($file:expr, $notice:expr) => {{
+        let comment = concat!(
+            "FIXME (overlay): These notices are extracted from files. Please ",
+            "review them before uploading to the archive."
+        );
+        Files::new(
+            $file,
+            $notice,
+            "UNKNOWN-LICENSE; FIXME (overlay)",
+            &fill(comment, 79),
+        )
+    }};
+}
+
+fn gen_files(debsrcdir: &Path) -> Result<Vec<Files>> {
+    let mut copyright_notices = BTreeMap::new();
+
+    let copyright_notice_re =
+        regex::Regex::new(r"(?:[Cc]opyright|©)(?:\s|[©:,()Cc<])*\b(\d{4}\b.*)$")?;
+
+    // Get current working directory and move inside the extracted source of
+    // crate. This is necessary in order to capture correct path for files in
+    // debian/copyright.
+    let current_dir = env::current_dir()?;
+    env::set_current_dir(debsrcdir)?;
+
+    // Here we specifically use "." to avoid absolute paths. If we use
+    // current_dir then we end up having absolute path from user home directory,
+    // which again messes debian/copyright.
+    // Use of . creates paths in format ./src/, so we strip the leading "./"
+    for entry in walkdir::WalkDir::new(".").sort_by(|a, b| a.file_name().cmp(b.file_name())) {
+        let entry = entry?;
+        if entry.file_type().is_file() {
+            let copyright_file = entry
+                .path()
+                .strip_prefix("./")?
+                .to_str()
+                .unwrap()
+                .to_string();
+            let file = fs::File::open(entry.path())?;
+            let reader = BufReader::new(file);
+            for line in reader.lines() {
+                if let Ok(line) = line {
+                    if let Some(m) = copyright_notice_re.captures(&line) {
+                        let m = m.get(1).unwrap();
+                        let start = m.start();
+                        let end = m.end();
+                        let notice = line[start..end]
+                            .trim_end()
+                            .trim_end_matches(". See the COPYRIGHT")
+                            .to_string();
+                        if !copyright_notices.contains_key(&copyright_file) {
+                            copyright_notices.insert(copyright_file.clone(), vec![]);
+                        }
+                        copyright_notices
+                            .get_mut(&copyright_file)
+                            .unwrap()
+                            .push(notice);
+                    }
+                } else {
+                    break;
+                }
+            }
+        }
+    }
+
+    // Restore back to original working directory as we can continue without
+    // problems.
+    env::set_current_dir(current_dir.as_path())?;
+
+    let mut notices: Vec<Files> = Vec::new();
+    for (filename, notice) in &copyright_notices {
+        notices.push(default_files!(filename, notice));
+    }
+
+    Ok(notices)
+}
+
+fn get_licenses(license: &str) -> Result<Vec<License>> {
+    let mut licenses = BTreeMap::new();
+    let sep = regex::Regex::new(r"(?i:(\s(or|and)\s|/))")?;
+    let known_licenses = vec![
+        ("agpl-3.0", include_str!("licenses/AGPL-3.0")),
+        ("apache-2.0", include_str!("licenses/Apache-2.0")),
+        ("bsd-2-clause", include_str!("licenses/BSD-2-Clause")),
+        ("bsd-3-clause", include_str!("licenses/BSD-3-Clause")),
+        ("cc0-1.0", include_str!("licenses/CC0-1.0")),
+        ("gpl-2.0", include_str!("licenses/GPL-2.0")),
+        ("gpl-3.0", include_str!("licenses/GPL-3.0")),
+        ("isc", include_str!("licenses/ISC")),
+        ("lgpl-2.0", include_str!("licenses/LGPL-2.0")),
+        ("lgpl-2.1", include_str!("licenses/LGPL-2.1")),
+        ("lgpl-3.0", include_str!("licenses/LGPL-3.0")),
+        ("mit", include_str!("licenses/MIT")),
+        ("mitnfa", include_str!("licenses/MITNFA")),
+        ("mpl-1.1", include_str!("licenses/MPL-1.1")),
+        ("mpl-2.0", include_str!("licenses/MPL-2.0")),
+        ("unlicense", include_str!("licenses/Unlicense")),
+        ("zlib", include_str!("licenses/Zlib")),
+    ]
+    .into_iter()
+    .collect::<BTreeMap<_, _>>();
+
+    let lses: Vec<&str> = sep.split(license).filter(|s| !s.is_empty()).collect();
+    for ls in lses {
+        let lname = ls
+            .trim()
+            .to_lowercase()
+            .trim_end_matches('+')
+            .trim_end_matches("-or-later")
+            .to_string();
+        let text = match known_licenses.get(lname.as_str()) {
+            Some(s) => s,
+            None => {
+                "FIXME (overlay): Unrecognized crate license, please find the \
+                     full license text in the rest of the crate source code and \
+                     copy-paste it here"
+            }
+        };
+        licenses.insert(ls.trim().to_string(), text.to_string());
+    }
+
+    let mut lblocks: Vec<License> = Vec::new();
+    if !licenses.is_empty() {
+        for (l, t) in licenses {
+            lblocks.push(License::new(l, t));
+        }
+    }
+
+    Ok(lblocks)
+}
+
+fn copyright_fromgit(repo_url: &str) -> Result<String> {
+    let tempdir = tempfile::Builder::new()
+        .prefix("debcargo")
+        .tempdir_in(".")?;
+    let repo = Repository::clone(repo_url, tempdir.path())?;
+
+    let mut revwalker = repo.revwalk()?;
+    revwalker.push_head()?;
+
+    // Get the latest and first commit id. This is a bit ugly
+    let latest_id = revwalker.next().unwrap()?;
+    let first_id = revwalker.last().unwrap()?; // revwalker ends here is consumed by last
+
+    let first_commit = repo.find_commit(first_id)?;
+    let latest_commit = repo.find_commit(latest_id)?;
+
+    let first_year = &DateTime::from_timestamp(first_commit.time().seconds(), 0)
+        .ok_or(anyhow::Error::msg("lo"))?
+        .year();
+
+    let latest_year = &DateTime::from_timestamp(latest_commit.time().seconds(), 0)
+        .ok_or(anyhow::Error::msg("lo"))?
+        .year();
+
+    let notice = match first_year.cmp(latest_year) {
+        Ordering::Equal => format!("{first_year}"),
+        _ => format!("{first_year}-{latest_year},"),
+    };
+
+    Ok(notice)
+}
+
+#[expect(clippy::too_many_arguments)]
+pub fn debian_copyright(
+    srcdir: &Path,
+    manifest: &manifest::Manifest,
+    manifest_path: &Path,
+    maintainer: &str,
+    uploaders: &[&str],
+    year_range: (i32, i32),
+    guess_harder: bool,
+    exclusions: &[String],
+) -> Result<DebCopyright> {
+    let meta = manifest.metadata().clone();
+    let repository = meta.repository.unwrap_or_default();
+
+    // The Authors field is optional according to
+    // https://rust-lang.github.io/rfcs/3052-optional-authors-field.html
+    // and crates.io publishes crates without the field already.
+    let unknown_authors = vec!["FIXME (overlay) UNKNOWN-AUTHORS".to_string()];
+    let authors = if meta.authors.is_empty() {
+        &unknown_authors
+    } else {
+        &meta.authors
+    };
+
+    let upstream = UpstreamInfo::new(manifest.name().to_string(), authors, &repository);
+
+    let mut licenses: Vec<License> = Vec::new();
+    let mut crate_license: String = String::new();
+
+    if let Some(ref license_file_name) = meta.license_file {
+        let license_file = manifest_path.with_file_name(license_file_name);
+        let mut text = Vec::new();
+        licenses.reserve(1);
+        let stext = match fs::File::open(license_file).and_then(|mut f| f.read_to_end(&mut text)) {
+            Ok(_) => String::from_utf8(text)?,
+            Err(e) => {
+                format!("Failed to read license from {license_file_name} - {e:?}")
+            }
+        };
+        licenses.push(License::new(
+            "UNKNOWN-LICENSE; FIXME (overlay)".to_string(),
+            stext,
+        ));
+    } else if let Some(ref license) = meta.license {
+        licenses = get_licenses(license)?;
+        crate_license = license
+            .trim()
+            .replace('/', " or ")
+            .replace(" OR ", " or ")
+            .replace(" AND ", " and ");
+    } else {
+        debcargo_bail!("Crate has no license or license_file");
+    }
+
+    let mut files = gen_files(srcdir)?;
+
+    let (y0, y1) = year_range;
+    let years = if y0 == y1 {
+        format!("{y0}")
+    } else {
+        format!("{y0}-{y1}")
+    };
+    let mut deb_notice = vec![format!("{} {}", years, maintainer)];
+    deb_notice.extend(uploaders.iter().map(|s| format!("{years} {s}")));
+    files.push(Files::new("debian/*", &deb_notice, &crate_license, ""));
+
+    // Insert catch all block as the first block of copyright file. Capture
+    // copyright notice from git log of the upstream repository.
+    let years = if guess_harder && !repository.is_empty() {
+        match copyright_fromgit(&repository) {
+            Ok(x) => x,
+            Err(e) => {
+                debcargo_warn!(
+                    "Failed to generate d/copyright from git repository {}: {}\n",
+                    repository,
+                    e
+                );
+                "FIXME (overlay) UNKNOWN-YEARS".to_string()
+            }
+        }
+    } else {
+        "FIXME (overlay) UNKNOWN-YEARS".to_string()
+    };
+    let notice = match meta.authors.len() {
+        0 => vec![format!("FIXME (overlay) UNKNOWN-AUTHORS {}", years)],
+        1 => vec![format!("{} {}", years, &meta.authors[0])],
+        _ => meta
+            .authors
+            .iter()
+            .map(|s| format!("{years} {s}"))
+            .collect(),
+    };
+    let comment = concat!(
+        "FIXME (overlay): Since upstream copyright years are not available ",
+        "in Cargo.toml, they were extracted from the upstream Git ",
+        "repository. This may not be correct information so you should ",
+        "review and fix this before uploading to the archive."
+    );
+    files.insert(
+        0,
+        Files::new("*", notice.as_slice(), &crate_license, &fill(comment, 79)),
+    );
+
+    Ok(DebCopyright::new(upstream, &files, &licenses, exclusions))
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/debian/copyright/tests.rs b/src/debian/copyright/tests.rs
new file mode 100644 (file)
index 0000000..e2eb7f8
--- /dev/null
@@ -0,0 +1,110 @@
+use super::{debian_copyright, get_licenses};
+
+use std::{io::Write, path::Path};
+
+use cargo::{
+    core::{package::Package, EitherManifest, SourceId},
+    GlobalContext,
+};
+use toml::toml;
+
+#[test]
+fn check_get_licenses() {
+    let test_data: &[(&str, &[(&str, bool)])] = &[
+        ("AGPL-3.0", &[("AGPL-3.0", true)]),
+        ("AcmeCorp-1.0", &[("AcmeCorp-1.0", false)]),
+        ("AGPL-3.0-or-later", &[("AGPL-3.0-or-later", true)]),
+        ("Apache-2.0/MIT", &[("Apache-2.0", true), ("MIT", true)]),
+        ("Apache-2.0 or MIT", &[("Apache-2.0", true), ("MIT", true)]),
+        (
+            "FooBar-1.0 AND MIT",
+            &[("FooBar-1.0", false), ("MIT", true)],
+        ),
+    ];
+    for (name, expected) in test_data {
+        let licenses = get_licenses(name).expect("getting licenses failed");
+        let found: Vec<_> = licenses
+            .iter()
+            .map(|l| (l.name.as_str(), !l.text.starts_with("FIXME")))
+            .collect();
+        assert_eq!(&found[..], &expected[..]);
+    }
+}
+
+#[test]
+fn check_debian_copyright_authors() {
+    let checks = vec![
+        (
+            vec![],
+            vec!["FIXME (overlay) UNKNOWN-AUTHORS FIXME (overlay) UNKNOWN-YEARS"],
+        ),
+        (
+            vec!["Jordan Doe"],
+            vec!["FIXME (overlay) UNKNOWN-YEARS Jordan Doe"],
+        ),
+        (
+            vec!["Jordan Doe", "Jane Doe"],
+            vec![
+                "FIXME (overlay) UNKNOWN-YEARS Jordan Doe",
+                "FIXME (overlay) UNKNOWN-YEARS Jane Doe",
+            ],
+        ),
+    ];
+
+    for (input, expected_output) in checks.into_iter() {
+        let package = build_package_with_authors(input);
+        let srcdir = tempfile::tempdir().unwrap();
+        let copyright = debian_copyright(
+            srcdir.path(),
+            package.manifest(),
+            package.manifest_path(),
+            "Jordan Doe",
+            &[],
+            (2000, 2020),
+            false,
+            &[],
+        )
+        .unwrap();
+        let mut generated = false;
+        for file in &copyright.files {
+            if file.files == "*" {
+                assert_eq!(file.copyright, expected_output);
+                generated = true;
+            }
+        }
+        assert!(generated);
+    }
+}
+
+fn build_package_with_authors(authors: Vec<&str>) -> Package {
+    let authors: Vec<String> = authors.into_iter().map(|s| s.to_string()).collect();
+    let toml = toml! {
+        [package]
+        name = "mypackage"
+        version = "1.2.3"
+        authors = authors
+        license = "AGPLv3"
+    };
+    let tmp_dir = tempfile::tempdir().unwrap();
+    let manifest_path = tmp_dir.path().join("Cargo.toml");
+    let mut manifest_file = std::fs::File::create(&manifest_path).unwrap();
+    manifest_file
+        .write_all(toml::to_string(&toml).unwrap().as_bytes())
+        .unwrap();
+
+    let src_dir = tmp_dir.path().join("src");
+    std::fs::create_dir(&src_dir).unwrap();
+    std::fs::File::create(src_dir.join("lib.rs")).unwrap();
+    #[cfg(unix)]
+    let package_root = Path::new("/");
+    #[cfg(windows)]
+    let package_root = Path::new("C:\\");
+    let source_id = SourceId::for_path(package_root).unwrap();
+    let context = GlobalContext::default().unwrap();
+    let manifest = cargo::util::toml::read_manifest(&manifest_path, source_id, &context).unwrap();
+    if let EitherManifest::Real(manifest) = manifest {
+        Package::new(manifest, Path::new("/path/to/manifest"))
+    } else {
+        unimplemented!();
+    }
+}
diff --git a/src/debian/dependency.rs b/src/debian/dependency.rs
new file mode 100644 (file)
index 0000000..4829229
--- /dev/null
@@ -0,0 +1,344 @@
+use cargo::core::Dependency;
+use itertools::Itertools;
+
+use std::cmp;
+use std::fmt;
+
+use crate::config::testing_ignore_debpolv;
+use crate::debian::dependency::V::{M, MM, MMP};
+use crate::debian::{self, control::base_deb_name, Package};
+use crate::errors::Result;
+use semver::Op::{Caret, Exact, Greater, GreaterEq, Less, LessEq, Tilde, Wildcard};
+
+#[derive(Eq, Clone)]
+#[allow(clippy::upper_case_acronyms)]
+enum V {
+    M(u64),
+    MM(u64, u64),
+    MMP(u64, u64, u64),
+}
+
+impl V {
+    fn new(p: &semver::Comparator) -> Result<Self> {
+        use self::V::{M, MM, MMP};
+        let mmp = match (p.minor, p.patch) {
+            (None, None) => M(p.major),
+            (Some(minor), None) => MM(p.major, minor),
+            (Some(minor), Some(patch)) => MMP(p.major, minor, patch),
+            (None, Some(_)) => debcargo_bail!("semver had patch without minor"),
+        };
+        Ok(mmp)
+    }
+
+    fn inclast(&self) -> V {
+        use self::V::{M, MM, MMP};
+        match *self {
+            M(major) => M(major + 1),
+            MM(major, minor) => MM(major, minor + 1),
+            MMP(major, minor, patch) => MMP(major, minor, patch + 1),
+        }
+    }
+
+    fn mmp(&self) -> (u64, u64, u64) {
+        use self::V::{M, MM, MMP};
+        match *self {
+            M(major) => (major, 0, 0),
+            MM(major, minor) => (major, minor, 0),
+            MMP(major, minor, patch) => (major, minor, patch),
+        }
+    }
+}
+
+impl Ord for V {
+    fn cmp(&self, other: &V) -> cmp::Ordering {
+        self.mmp().cmp(&other.mmp())
+    }
+}
+
+impl PartialOrd for V {
+    fn partial_cmp(&self, other: &V) -> Option<cmp::Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl PartialEq for V {
+    fn eq(&self, other: &V) -> bool {
+        self.mmp() == other.mmp()
+    }
+}
+
+impl fmt::Display for V {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use self::V::{M, MM, MMP};
+        match *self {
+            M(major) => write!(f, "{major}"),
+            MM(major, minor) => write!(f, "{major}.{minor}"),
+            MMP(major, minor, patch) => write!(f, "{major}.{minor}.{patch}"),
+        }
+    }
+}
+
+struct VRange {
+    ge: Option<V>,
+    lt: Option<V>,
+}
+
+impl VRange {
+    fn new() -> Self {
+        VRange { ge: None, lt: None }
+    }
+
+    fn constrain_ge(&mut self, ge: V) -> &Self {
+        match self.ge {
+            Some(ref ge_) if &ge < ge_ => (),
+            _ => self.ge = Some(ge),
+        }
+        self
+    }
+
+    fn constrain_lt(&mut self, lt: V) -> &Self {
+        match self.lt {
+            Some(ref lt_) if &lt >= lt_ => (),
+            _ => self.lt = Some(lt),
+        }
+        self
+    }
+
+    fn to_deb_clause(&self, base: &str, suffix: &str) -> Result<Vec<String>> {
+        use debian::dependency::V::{M, MM};
+        match (&self.ge, &self.lt) {
+            (None, None) => Ok(vec![format!("{}{}", base, suffix)]),
+            (Some(ge), None) => Ok(vec![format!("{}{} (>= {})", base, suffix, ge)]),
+            (None, Some(lt)) => Ok(vec![format!("{}{} (<< {})", base, suffix, lt)]),
+            (Some(ge), Some(lt)) => {
+                if ge >= lt {
+                    debcargo_bail!("bad version range: >= {}, << {}", ge, lt);
+                }
+                let mut ranges = vec![];
+                let (lt_maj, lt_min, lt_pat) = lt.mmp();
+                let (ge_maj, ge_min, _ge_pat) = ge.mmp();
+
+                if ge_maj + 1 == lt_maj && lt_min == 0 && lt_pat == 0 {
+                    // upper bound doesn't restrict lower bound further if we include the major
+                    // part
+                    ranges.push((Some(M(ge_maj)), true, ge));
+                } else if ge_maj < lt_maj {
+                    // different major versions, unversioned package needs to satisfy
+                    ranges.push((None, true, ge));
+                    ranges.push((None, false, lt));
+                } else {
+                    assert_eq!(ge_maj, lt_maj);
+                    if ge_maj == 0 && ge_min + 1 == lt_min && lt_pat == 0 {
+                        // upper bound doesn't restrict lower bound further if we include 0.X
+                        ranges.push((Some(MM(ge_maj, ge_min)), true, ge));
+                    } else if ge_maj == 0 && ge_min < lt_min {
+                        // different 0.X versions, unversioned package needs to satisfy
+                        ranges.push((None, true, ge));
+                        ranges.push((None, false, lt));
+                    } else if ge_min < lt_min {
+                        // different minor versions within a major version, any package with the
+                        // corresponding major version can potentially satisfy
+                        ranges.push((Some(M(ge_maj)), true, ge));
+                        ranges.push((Some(M(lt_maj)), false, lt));
+                    } else {
+                        // just the patch level differs, but both ends restricted
+                        // any package with the corresponding major.minor version can potentially
+                        // satisfy
+                        assert_eq!(ge_min, lt_min);
+                        ranges.push((Some(MM(ge_maj, ge_min)), true, ge));
+                        ranges.push((Some(MM(lt_maj, lt_min)), false, lt));
+                    }
+                }
+                // unversioned package name is only provided by the non semver-suffixed packages
+                // if a range is only satisfiable by semver-suffixed variants in the archive, it
+                // needs to be collapsed/reduced accordingly
+                Ok(ranges
+                    .iter()
+                    .filter_map(|(ver, greater, cons)| match (ver, greater, cons) {
+                        (None, true, c) => Some(format!("{base}{suffix} (>= {c})")),
+                        (None, false, c) => Some(format!("{base}{suffix} (<< {c})")),
+                        (Some(ver), true, c) => {
+                            if c == &ver {
+                                // A-x >= x is redundant, drop the >=
+                                Some(format!("{base}-{ver}{suffix}"))
+                            } else {
+                                Some(format!("{base}-{ver}{suffix} (>= {c})"))
+                            }
+                        }
+                        (Some(ver), false, c) => {
+                            if c == &ver {
+                                // A-x << x is unsatisfiable, drop it
+                                None
+                            } else {
+                                Some(format!("{base}-{ver}{suffix} (<< {c})"))
+                            }
+                        }
+                    })
+                    .collect())
+            }
+        }
+    }
+}
+
+fn coerce_unacceptable_predicate<'a>(
+    dep: &Dependency,
+    p: &'a semver::Comparator,
+    allow_prerelease_deps: bool,
+) -> Result<&'a semver::Op> {
+    let mmp = &V::new(p)?;
+
+    // Cargo/semver and Debian handle pre-release versions quite
+    // differently, so a versioned Debian dependency cannot properly
+    // handle pre-release crates. This might be OK most of the time,
+    // coerce it to the non-pre-release version.
+    if !p.pre.is_empty() {
+        if allow_prerelease_deps || testing_ignore_debpolv() {
+            debcargo_warn!(
+                "Coercing removal of prerelease part of dependency: {} {:?}",
+                dep.package_name(),
+                p
+            );
+        } else {
+            debcargo_bail!(
+                "Cannot represent prerelease part of dependency: {} {:?}",
+                dep.package_name(),
+                p
+            )
+        }
+    }
+
+    match (&p.op, mmp) {
+        (&Greater, &M(0)) => Ok(&p.op),
+        (&GreaterEq, &M(0)) => {
+            debcargo_warn!(
+                "Coercing unrepresentable dependency version predicate 'GtEq 0' to 'Gt 0': {} {:?}",
+                dep.package_name(),
+                p
+            );
+            Ok(&Greater)
+        }
+        // TODO: This will prevent us from handling wildcard dependencies with
+        // 0.0.0* so for now commenting this out.
+        // (_, &M(0)) => debcargo_bail!(
+        //     "Unrepresentable dependency version predicate: {} {:?}",
+        //     dep.package_name(),
+        //     p
+        // ),
+        (_, _) => Ok(&p.op),
+    }
+}
+
+fn generate_version_constraints(
+    vr: &mut VRange,
+    dep: &Dependency,
+    p: &semver::Comparator,
+    op: &semver::Op,
+) -> Result<()> {
+    let mmp = V::new(p)?;
+    // see https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
+    // and https://docs.rs/semver/1/semver/enum.Op.html for semantics
+    match (*op, &mmp) {
+        (Less, &M(0) | &MM(0, 0) | &MMP(0, 0, 0)) => debcargo_bail!(
+            "Unrepresentable dependency version predicate: {} {:?}",
+            dep.package_name(),
+            p
+        ),
+        (Less, _) => {
+            vr.constrain_lt(mmp);
+        }
+        (LessEq, _) => {
+            vr.constrain_lt(mmp.inclast());
+        }
+        (Greater, _) => {
+            vr.constrain_ge(mmp.inclast());
+        }
+        (GreaterEq, _) => {
+            vr.constrain_ge(mmp);
+        }
+        (Exact | Wildcard, _) => {
+            vr.constrain_lt(mmp.inclast());
+            vr.constrain_ge(mmp);
+        }
+        (Tilde, &M(_) | &MM(_, _)) => {
+            vr.constrain_lt(mmp.inclast());
+            vr.constrain_ge(mmp);
+        }
+        (Tilde, &MMP(major, minor, _)) => {
+            vr.constrain_lt(MM(major, minor + 1));
+            vr.constrain_ge(mmp);
+        }
+
+        (Caret, &MMP(0, 0, _)) => {
+            vr.constrain_lt(mmp.inclast());
+            vr.constrain_ge(mmp);
+        }
+        (Caret, &MMP(0, minor, _) | &MM(0, minor)) => {
+            vr.constrain_lt(MM(0, minor + 1));
+            vr.constrain_ge(mmp);
+        }
+        (Caret, &MMP(major, _, _) | &MM(major, _) | &M(major)) => {
+            vr.constrain_lt(M(major + 1));
+            vr.constrain_ge(mmp);
+        }
+
+        (_, _) => {
+            // https://github.com/dtolnay/semver/issues/262
+            panic!("Op is non-exhaustive for some reason");
+        }
+    }
+
+    Ok(())
+}
+
+/// Translates a Cargo dependency into a Debian package dependency.
+pub fn deb_dep(allow_prerelease_deps: bool, dep: &Dependency) -> Result<Vec<String>> {
+    let dep_dashed = base_deb_name(&dep.package_name());
+    let mut suffixes = Vec::new();
+    if dep.uses_default_features() {
+        suffixes.push("+default-dev".to_string());
+    }
+    for feature in dep.features() {
+        suffixes.push(format!("+{}-dev", base_deb_name(feature)));
+    }
+    if suffixes.is_empty() {
+        suffixes.push("-dev".to_string());
+    }
+    let req = semver::VersionReq::parse(&dep.version_req().to_string())?;
+    let mut deps = Vec::new();
+    for suffix in suffixes {
+        let base = format!("{}-{}", Package::pkg_prefix(), dep_dashed);
+        let mut vr = VRange::new();
+        for p in &req.comparators {
+            let op = coerce_unacceptable_predicate(dep, p, allow_prerelease_deps)?;
+            generate_version_constraints(&mut vr, dep, p, op)?;
+        }
+        deps.extend(vr.to_deb_clause(&base, &suffix)?);
+    }
+    Ok(deps)
+}
+
+pub fn deb_deps(allow_prerelease_deps: bool, cdeps: &[Dependency]) -> Result<Vec<String>> // result is an AND-clause
+{
+    let mut deps = Vec::new();
+    for dep in cdeps {
+        deps.extend(
+            deb_dep(allow_prerelease_deps, dep)?
+                .iter()
+                .map(String::to_string),
+        );
+    }
+    deps.sort();
+    deps.dedup();
+    Ok(deps)
+}
+
+pub fn deb_dep_add_nocheck(x: &str) -> String {
+    x.split('|')
+        .map(|x| x.trim_end().to_string() + " <!nocheck> ")
+        .join("|")
+        .trim_end()
+        .to_string()
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/debian/dependency/tests.rs b/src/debian/dependency/tests.rs
new file mode 100644 (file)
index 0000000..a197bf6
--- /dev/null
@@ -0,0 +1,277 @@
+use crate::debian::deb_dep_add_nocheck;
+use crate::debian::dependency::{VRange, V};
+
+#[test]
+fn test_v_new_mmp() {
+    let v = V::new(&semver::Comparator::parse("0.9.7").unwrap()).unwrap();
+
+    assert_eq!((0, 9, 7), v.mmp());
+}
+
+#[test]
+fn test_v_new_inclast() {
+    let v = V::new(&semver::Comparator::parse("0.9.7").unwrap()).unwrap();
+
+    assert_eq!((0, 9, 8), v.inclast().mmp());
+}
+
+#[test]
+fn test_v_neq() {
+    let v1 = V::new(&semver::Comparator::parse("0.9.7").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.9.8").unwrap()).unwrap();
+
+    assert!(v1 != v2);
+}
+
+#[test]
+fn test_v_eq() {
+    let v1 = V::new(&semver::Comparator::parse("0.10.0").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.10").unwrap()).unwrap();
+
+    assert!(v1 == v2);
+}
+
+#[test]
+fn test_v_display() {
+    let v1 = V::new(&semver::Comparator::parse("0").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.10").unwrap()).unwrap();
+    let v3 = V::new(&semver::Comparator::parse("0.10.0").unwrap()).unwrap();
+
+    assert_eq!("0", v1.to_string());
+    assert_eq!("0.10", v2.to_string());
+    assert_eq!("0.10.0", v3.to_string());
+}
+
+#[test]
+fn test_v_range() {
+    let v1 = V::new(&semver::Comparator::parse("0.9").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.10").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    assert!(vr.ge.is_none());
+    assert!(vr.lt.is_none());
+
+    vr.constrain_ge(v1.clone());
+    assert!(vr.ge.is_some());
+    assert!(vr.ge.as_ref().unwrap() == &v1);
+    assert!(vr.ge.as_ref().unwrap() < &v2);
+    assert!(vr.lt.is_none());
+
+    vr.constrain_lt(v2.clone());
+    assert!(vr.ge.is_some());
+    assert!(vr.lt.is_some());
+    assert!(vr.ge.as_ref().unwrap() == &v1);
+    assert!(vr.lt.as_ref().unwrap() == &v2);
+}
+
+#[test]
+fn test_v_range_to_deb_clause_empty() {
+    let vr = VRange::new();
+
+    assert_eq!(
+        vec!["base+feature"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_ge_only() {
+    let v1 = V::new(&semver::Comparator::parse("0.9").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+
+    assert_eq!(
+        vec!["base+feature (>= 0.9)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_lt_only() {
+    let v1 = V::new(&semver::Comparator::parse("0.10").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_lt(v1);
+
+    assert_eq!(
+        vec!["base+feature (<< 0.10)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_minor_one_apart() {
+    let v1 = V::new(&semver::Comparator::parse("0.9").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.10").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base-0.9+feature"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_minor_two_apart() {
+    let v1 = V::new(&semver::Comparator::parse("0.9").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.11").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base+feature (>= 0.9)", "base+feature (<< 0.11)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_minor_complicated_apart() {
+    let v1 = V::new(&semver::Comparator::parse(">= 0.1.2").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.4").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base+feature (>= 0.1.2)", "base+feature (<< 0.4)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_minor_complicated() {
+    let v1 = V::new(&semver::Comparator::parse(">= 0.1.2").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.1.5").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base-0.1+feature (>= 0.1.2)", "base-0.1+feature (<< 0.1.5)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_minor_more_complicated_apart() {
+    let v1 = V::new(&semver::Comparator::parse(">= 0.1.2").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.4.5").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base+feature (>= 0.1.2)", "base+feature (<< 0.4.5)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_major_one_apart() {
+    let v1 = V::new(&semver::Comparator::parse("9.0").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("10.0").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base-9+feature"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_major_two_apart() {
+    let v1 = V::new(&semver::Comparator::parse("9.0").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("11.0").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base+feature (>= 9.0)", "base+feature (<< 11.0)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_major_complicated_apart() {
+    let v1 = V::new(&semver::Comparator::parse(">= 1.2.3").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("4.0").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base+feature (>= 1.2.3)", "base+feature (<< 4.0)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_major_complicated() {
+    let v1 = V::new(&semver::Comparator::parse(">= 1.2.3").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("1.9.9").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base-1+feature (>= 1.2.3)", "base-1+feature (<< 1.9.9)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_major_more_complicated_apart() {
+    let v1 = V::new(&semver::Comparator::parse(">= 1.2.3").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("4.5.6").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base+feature (>= 1.2.3)", "base+feature (<< 4.5.6)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_bad_range() {
+    let v1 = V::new(&semver::Comparator::parse("9.0").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("11.0").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v2);
+    vr.constrain_lt(v1);
+
+    let err = vr.to_deb_clause("base", "+feature");
+    assert!(err.is_err());
+    assert_eq!(
+        "bad version range: >= 11.0, << 9.0",
+        err.unwrap_err().to_string()
+    );
+}
+
+#[test]
+fn test_deb_dep_add_nocheck() {
+    let result = deb_dep_add_nocheck(" librust-sequoia-policy-config-0.7+default-dev | librust-sequoia-policy-config-0.6+default-dev");
+
+    let expected = " librust-sequoia-policy-config-0.7+default-dev <!nocheck> | librust-sequoia-policy-config-0.6+default-dev <!nocheck>";
+
+    assert_eq!(expected, result);
+}
diff --git a/src/debian/licenses/AGPL-3.0 b/src/debian/licenses/AGPL-3.0
new file mode 100644 (file)
index 0000000..dba13ed
--- /dev/null
@@ -0,0 +1,661 @@
+                    GNU AFFERO GENERAL PUBLIC LICENSE
+                       Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+  A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate.  Many developers of free software are heartened and
+encouraged by the resulting cooperation.  However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+  The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community.  It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server.  Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+  An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals.  This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU Affero General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Remote Network Interaction; Use with the GNU General Public License.
+
+  Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software.  This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time.  Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source.  For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code.  There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+<http://www.gnu.org/licenses/>.
diff --git a/src/debian/licenses/Apache-2.0 b/src/debian/licenses/Apache-2.0
new file mode 100644 (file)
index 0000000..d69cdd1
--- /dev/null
@@ -0,0 +1,2 @@
+Debian systems provide the Apache 2.0 license in
+/usr/share/common-licenses/Apache-2.0
diff --git a/src/debian/licenses/BSD-2-Clause b/src/debian/licenses/BSD-2-Clause
new file mode 100644 (file)
index 0000000..d17fad3
--- /dev/null
@@ -0,0 +1,20 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/debian/licenses/BSD-3-Clause b/src/debian/licenses/BSD-3-Clause
new file mode 100644 (file)
index 0000000..689c723
--- /dev/null
@@ -0,0 +1,24 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+may be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/debian/licenses/CC0-1.0 b/src/debian/licenses/CC0-1.0
new file mode 100644 (file)
index 0000000..e37e562
--- /dev/null
@@ -0,0 +1,2 @@
+Debian systems provide the CC0 1.0 Universal License in
+/usr/share/common-licenses/CC0-1.0
diff --git a/src/debian/licenses/GPL-2.0 b/src/debian/licenses/GPL-2.0
new file mode 100644 (file)
index 0000000..0c94208
--- /dev/null
@@ -0,0 +1 @@
+Debian systems provide the GPL 2.0 in /usr/share/common-licenses/GPL-2
diff --git a/src/debian/licenses/GPL-3.0 b/src/debian/licenses/GPL-3.0
new file mode 100644 (file)
index 0000000..4e80768
--- /dev/null
@@ -0,0 +1 @@
+Debian systems provide the GPL 3.0 in /usr/share/common-licenses/GPL-3
diff --git a/src/debian/licenses/ISC b/src/debian/licenses/ISC
new file mode 100644 (file)
index 0000000..8351a30
--- /dev/null
@@ -0,0 +1,11 @@
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/src/debian/licenses/LGPL-2.0 b/src/debian/licenses/LGPL-2.0
new file mode 100644 (file)
index 0000000..5fa5065
--- /dev/null
@@ -0,0 +1 @@
+Debian systems provide the LGPL 2.0 in /usr/share/common-licenses/LGPL-2
diff --git a/src/debian/licenses/LGPL-2.1 b/src/debian/licenses/LGPL-2.1
new file mode 100644 (file)
index 0000000..32f41bb
--- /dev/null
@@ -0,0 +1 @@
+Debian systems provide the LGPL 2.1 in /usr/share/common-licenses/LGPL-2.1
diff --git a/src/debian/licenses/LGPL-3.0 b/src/debian/licenses/LGPL-3.0
new file mode 100644 (file)
index 0000000..91e41a7
--- /dev/null
@@ -0,0 +1 @@
+Debian systems provide the LGPL 3.0 in /usr/share/common-licenses/LGPL-3
diff --git a/src/debian/licenses/MIT b/src/debian/licenses/MIT
new file mode 100644 (file)
index 0000000..50b3cf0
--- /dev/null
@@ -0,0 +1,17 @@
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/debian/licenses/MITNFA b/src/debian/licenses/MITNFA
new file mode 100644 (file)
index 0000000..8eff3c8
--- /dev/null
@@ -0,0 +1,29 @@
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+Distributions of all or part of the Software intended to be used
+by the recipients as they would use the unmodified Software,
+containing modifications that substantially alter, remove, or
+disable functionality of the Software, outside of the documented
+configuration mechanisms provided by the Software, shall be
+modified such that the Original Author's bug reporting email
+addresses and urls are either replaced with the contact information
+of the parties responsible for the changes, or removed entirely.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/src/debian/licenses/MPL-1.1 b/src/debian/licenses/MPL-1.1
new file mode 100644 (file)
index 0000000..f07159d
--- /dev/null
@@ -0,0 +1 @@
+Debian systems provide the MPL 1.1 in /usr/share/common-licenses/MPL-1.1
diff --git a/src/debian/licenses/MPL-2.0 b/src/debian/licenses/MPL-2.0
new file mode 100644 (file)
index 0000000..8dcf8f1
--- /dev/null
@@ -0,0 +1 @@
+Debian systems provide the MPL 2.0 in /usr/share/common-licenses/MPL-2.0
diff --git a/src/debian/licenses/Unlicense b/src/debian/licenses/Unlicense
new file mode 100644 (file)
index 0000000..b3dbff0
--- /dev/null
@@ -0,0 +1,22 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/src/debian/licenses/Zlib b/src/debian/licenses/Zlib
new file mode 100644 (file)
index 0000000..480c61e
--- /dev/null
@@ -0,0 +1,15 @@
+This software is provided 'as-is', without any express or implied
+warranty.  In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software. If you use this software
+   in a product, an acknowledgment in the product documentation would be
+   appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
diff --git a/src/debian/mod.rs b/src/debian/mod.rs
new file mode 100644 (file)
index 0000000..c99f185
--- /dev/null
@@ -0,0 +1,1422 @@
+use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
+use std::fs;
+use std::io::{self, ErrorKind, Read, Seek, Write as IoWrite};
+#[cfg(unix)]
+use std::os::unix::fs::PermissionsExt;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+use std::str::FromStr;
+
+use anyhow::format_err;
+use chrono::{self, Datelike};
+use control::BuildDeps;
+use flate2::read::GzDecoder;
+use flate2::write::GzEncoder;
+use flate2::Compression;
+use itertools::Itertools;
+use regex::Regex;
+use tar::{Archive, Builder};
+use tempfile;
+
+use crate::config::{package_field_for_feature, testing_ignore_debpolv, Config, PackageKey};
+use crate::crates::{
+    all_dependencies_and_features, show_dep, transitive_deps, CrateDepInfo, CrateInfo,
+};
+use crate::errors::Result;
+use crate::util::{self, copy_tree, expect_success, get_transitive_val, traverse_depth};
+
+use self::changelog::{ChangelogEntry, ChangelogIterator};
+use self::control::{base_deb_name, deb_upstream_version};
+use self::control::{Description, Package, PkgTest, Source};
+use self::copyright::debian_copyright;
+pub use self::dependency::{deb_dep_add_nocheck, deb_deps};
+
+pub mod changelog;
+pub mod control;
+pub mod copyright;
+mod dependency;
+
+pub struct DebInfo {
+    upstream_name: String,
+    /// Debian package name without `rust-` prefix or any semver suffix
+    base_package_name: String,
+    /// Package name suffix after the base package name.
+    /// Some implies `semver_suffix`, i.e. Some("") is different from None
+    name_suffix: Option<String>,
+    uscan_version_pattern: Option<String>,
+    /// Debian package name without `rust-` prefix
+    package_name: String,
+    deb_upstream_version: String,
+    debcargo_version: String,
+    package_source_dir: PathBuf,
+    orig_tarball_path: PathBuf,
+}
+
+impl DebInfo {
+    pub fn new(
+        crate_info: &CrateInfo,
+        debcargo_version: &str,
+        semver_suffix: bool,
+        repack_suffix: Option<&str>,
+    ) -> Self {
+        let upstream_name = crate_info.package_id().name().to_string();
+        let name_dashed = base_deb_name(&upstream_name);
+        let base_package_name = name_dashed.to_lowercase();
+        let (name_suffix, uscan_version_pattern, package_name) = if semver_suffix {
+            let semver = crate_info.semver();
+            let name_suffix = format!("-{}", &semver);
+            // See `man uscan` description of @ANY_VERSION@ on how these
+            // regex patterns were built.
+            let uscan = format!("[-_]?({}\\.\\d[\\-+\\.:\\~\\da-zA-Z]*)", &semver);
+            let pkgname = format!("{}{}", base_package_name, &name_suffix);
+            (Some(name_suffix), Some(uscan), pkgname)
+        } else {
+            (None, None, base_package_name.clone())
+        };
+        let deb_upstream_version = deb_upstream_version(crate_info.version(), repack_suffix);
+        let package_source_dir = PathBuf::from(format!(
+            "{}-{}-{}",
+            Source::pkg_prefix(),
+            package_name,
+            deb_upstream_version
+        ));
+        let orig_tarball_path = PathBuf::from(format!(
+            "{}-{}_{}.orig.tar.gz",
+            Source::pkg_prefix(),
+            package_name,
+            deb_upstream_version
+        ));
+
+        DebInfo {
+            upstream_name,
+            base_package_name,
+            name_suffix,
+            uscan_version_pattern,
+            package_name,
+            deb_upstream_version,
+            debcargo_version: debcargo_version.to_string(),
+            package_source_dir,
+            orig_tarball_path,
+        }
+    }
+
+    pub fn upstream_name(&self) -> &str {
+        self.upstream_name.as_str()
+    }
+
+    pub fn base_package_name(&self) -> &str {
+        self.base_package_name.as_str()
+    }
+
+    pub fn name_suffix(&self) -> Option<&str> {
+        self.name_suffix.as_deref()
+    }
+
+    pub fn package_name(&self) -> &str {
+        self.package_name.as_str()
+    }
+
+    pub fn deb_upstream_version(&self) -> &str {
+        self.deb_upstream_version.as_str()
+    }
+
+    pub fn debcargo_version(&self) -> &str {
+        self.debcargo_version.as_str()
+    }
+
+    pub fn package_source_dir(&self) -> &Path {
+        self.package_source_dir.as_ref()
+    }
+
+    pub fn orig_tarball_path(&self) -> &Path {
+        self.orig_tarball_path.as_ref()
+    }
+}
+
+pub fn prepare_orig_tarball(
+    crate_info: &CrateInfo,
+    tarball: &Path,
+    repacked: bool,
+    manifest_normalized: bool,
+    output_dir: &Path,
+) -> Result<()> {
+    let crate_file = crate_info.crate_file();
+    let tempdir = tempfile::Builder::new()
+        .prefix("debcargo")
+        .tempdir_in(".")?;
+    let temp_archive_path = tempdir.path().join(tarball);
+
+    let mut create = fs::OpenOptions::new();
+    create.write(true).create_new(true);
+
+    if repacked {
+        debcargo_info!("crate tarball was modified; repacking for debian");
+        let mut f = crate_file.file();
+        f.seek(io::SeekFrom::Start(0))?;
+        let mut archive = Archive::new(GzDecoder::new(f));
+        let mut new_archive = Builder::new(GzEncoder::new(
+            create.open(&temp_archive_path)?,
+            Compression::best(),
+        ));
+        let mut manifest_handled = false;
+
+        for entry in archive.entries()? {
+            let entry = entry?;
+            let path = entry.path()?.into_owned();
+            if manifest_normalized
+                && (path.ends_with("Cargo.toml") || path.ends_with("Cargo.toml.orig"))
+                && path.iter().count() == 2
+            {
+                // Put the rewritten and original Cargo.toml back into the orig tarball
+                let mut new_archive_append = |name: &str| {
+                    let mut header = entry.header().clone();
+                    let srcpath = output_dir.join(name);
+                    header.set_path(path.parent().unwrap().join(name))?;
+                    header.set_size(fs::metadata(&srcpath)?.len());
+                    if name == "Cargo.toml" {
+                        // Cargo.toml has epoch 1
+                        header.set_mtime(1);
+                    } else {
+                        // the rest have epoch tar::headers::DETERMINISTIC_TIMESTAMP
+                        // FIXME once exposed publically in the tar crate
+                        header.set_mtime(1153704088);
+                    }
+                    header.set_cksum();
+                    new_archive.append(&header, fs::File::open(&srcpath)?)
+                };
+                if !manifest_handled {
+                    new_archive_append("Cargo.toml")?;
+                    new_archive_append("Cargo.toml.orig")?;
+                }
+                manifest_handled = true;
+            } else {
+                match crate_info.filter_path(&entry.path()?) {
+                    Err(e) => debcargo_bail!(e),
+                    Ok(r) => {
+                        if r {
+                            writeln!(
+                                io::stderr(),
+                                "Filtered out files from .orig.tar.gz: {:?}",
+                                &entry.path()?
+                            )?;
+                        } else {
+                            new_archive.append_data(&mut entry.header().clone(), path, entry)?;
+                        }
+                    }
+                }
+            }
+        }
+
+        new_archive.finish()?;
+    } else {
+        fs::copy(crate_file.path(), &temp_archive_path)?;
+    }
+
+    fs::rename(temp_archive_path, tarball)?;
+    Ok(())
+}
+
+pub fn apply_overlay_and_patches(
+    crate_info: &mut CrateInfo,
+    config_path: Option<&Path>,
+    config: &Config,
+    output_dir: &Path,
+) -> Result<tempfile::TempDir> {
+    let tempdir = tempfile::Builder::new()
+        .prefix("debcargo")
+        .tempdir_in(".")?;
+    let overlay = config.overlay_dir(config_path);
+    if let Some(p) = overlay.as_ref() {
+        for anc in tempdir.path().ancestors() {
+            if p.as_path() == anc {
+                debcargo_bail!(
+                    "Aborting: refusing to copy an ancestor {} into a descendant {}",
+                    p.as_path().display(),
+                    tempdir.path().display(),
+                );
+            }
+        }
+        copy_tree(p.as_path(), tempdir.path())?;
+    }
+    if tempdir.path().join("control").exists() {
+        debcargo_warn!(
+            "Most of the time you shouldn't overlay debian/control, \
+it's a maintenance burden. Use debcargo.toml instead."
+        );
+    }
+    // apply patches to Cargo.toml in case they exist, and re-read it
+    if tempdir.path().join("patches").join("series").exists() {
+        debcargo_info!("applying patches..");
+        let output_dir = &fs::canonicalize(output_dir)?;
+        let stderr = || {
+            // create a new owned handle to stderr
+            fs::OpenOptions::new()
+                .append(true)
+                .open("/dev/stderr")
+                .unwrap()
+        };
+        // common case, patches might need rebasing!
+        if let Err(err) = expect_success(
+            Command::new("quilt")
+                .stdout(stderr())
+                .current_dir(output_dir)
+                .env("QUILT_PATCHES", tempdir.path().join("patches"))
+                .args(["push", "--quiltrc=-", "-a"]),
+            "failed to apply patches using quilt",
+        ) {
+            debcargo_warn!(format!("{err}, attempting cleanup"));
+            let _ = expect_success(
+                Command::new("quilt")
+                    .stdout(stderr())
+                    .current_dir(output_dir)
+                    .env("QUILT_PATCHES", tempdir.path().join("patches"))
+                    .args(["pop", "--quiltrc=-", "-a", "-f"]),
+                "failed to unapply partially applied patches",
+            );
+            fs::remove_dir_all(output_dir.join(".pc"))?;
+            debcargo_bail!("applying patches failed! see above for details..");
+        }
+        debcargo_info!("reloading Cargo.toml..");
+        crate_info.replace_manifest(&output_dir.join("Cargo.toml"))?;
+
+        // this should never fail!
+        debcargo_info!("unapplying patches again..");
+        expect_success(
+            Command::new("quilt")
+                .stdout(stderr())
+                .current_dir(output_dir)
+                .env("QUILT_PATCHES", tempdir.path().join("patches"))
+                .args(["pop", "--quiltrc=-", "-a"]),
+            "failed to unapply patches",
+        )?;
+        fs::remove_dir_all(output_dir.join(".pc"))?;
+    }
+    Ok(tempdir)
+}
+
+#[allow(clippy::too_many_arguments)]
+pub fn prepare_debian_folder(
+    crate_info: &mut CrateInfo,
+    deb_info: &DebInfo,
+    config_path: Option<&Path>,
+    config: &Config,
+    output_dir: &Path,
+    tempdir: &tempfile::TempDir,
+    changelog_ready: bool,
+    copyright_guess_harder: bool,
+    overlay_write_back: bool,
+) -> Result<()> {
+    let mut create = fs::OpenOptions::new();
+    create.write(true).create_new(true);
+
+    let crate_name = crate_info.package_id().name();
+    let crate_version = crate_info.package_id().version();
+    let upstream_name = deb_info.upstream_name();
+
+    let maintainer = config.maintainer();
+    let uploaders: Vec<&str> = config
+        .uploaders()
+        .into_iter()
+        .flatten()
+        .map(String::as_str)
+        .collect();
+
+    let mut new_hints = vec![];
+    let mut file = |name: &str| {
+        let path = tempdir.path();
+        let f = path.join(name);
+        fs::create_dir_all(f.parent().unwrap())?;
+        create.open(&f).or_else(|e| match e.kind() {
+            ErrorKind::AlreadyExists => {
+                let hintname = name.to_owned() + util::HINT_SUFFIX;
+                let hint = path.join(&hintname);
+                if hint.exists() {
+                    fs::remove_file(&hint)?;
+                }
+                new_hints.push(hintname);
+                create.open(&hint)
+            }
+            _ => Err(e),
+        })
+    };
+
+    // debian/cargo-checksum.json
+    {
+        let checksum = crate_info
+            .checksum()
+            .unwrap_or("Could not get crate checksum");
+        let mut cargo_checksum_json = file("cargo-checksum.json")?;
+        writeln!(
+            cargo_checksum_json,
+            r#"{{"package":"{checksum}","files":{{}}}}"#
+        )?;
+    }
+
+    // debian/copyright
+    {
+        let mut copyright = io::BufWriter::new(file("copyright")?);
+        let year_range = if changelog_ready {
+            // if changelog is ready, unconditionally read the year range from it
+            changelog_first_last(tempdir.path())?
+        } else {
+            // otherwise use the first date if it exists
+            let last = chrono::Local::now().year();
+            match changelog_first_last(tempdir.path()) {
+                Ok((first, _)) => (first, last),
+                Err(_) => (last, last),
+            }
+        };
+        let excludes = config.excludes.as_deref().unwrap_or_default();
+        let dep5_copyright = debian_copyright(
+            output_dir,
+            crate_info.manifest(),
+            crate_info.manifest_path(),
+            maintainer,
+            &uploaders,
+            year_range,
+            copyright_guess_harder,
+            excludes,
+        )?;
+        write!(copyright, "{dep5_copyright}")?;
+    }
+
+    // debian/watch
+    {
+        let mut watch = file("watch")?;
+        if config.crate_src_path(config_path).is_some() {
+            write!(watch, "FIXME add uscan directive for local crate")?;
+        } else {
+            let uscan_version_pattern = deb_info
+                .uscan_version_pattern
+                .as_ref()
+                .map_or_else(|| "@ANY_VERSION@".to_string(), ToString::to_string);
+            writeln!(watch, "Version: 5\n")?;
+            writeln!(
+                watch,
+                "Source: https://qa.debian.org/cgi-bin/fakeupstream.cgi?upstream=crates.io/{upstream_name}",
+            )?;
+            writeln!(
+                watch,
+                "Matching-Pattern:  .*/crates/{upstream_name}/{uscan_version_pattern}/download"
+            )?;
+            writeln!(
+                watch,
+                r"Filenamemangle: s/.*\/(.*)\/download/{upstream_name}-$1\.tar\.gz/g",
+            )?;
+            writeln!(
+                watch,
+                r"Uversionmangle: s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha)\.?\d*)$/$1~$2/"
+            )?;
+            writeln!(watch, r"Dversionmangle: s/@DEB_EXT@//g",)?;
+            writeln!(watch, r"Compression: gzip")?;
+            if let Some(repack_suffix) = config.repack_suffix() {
+                writeln!(watch, r"Repack: yes")?;
+                writeln!(watch, r"Repacksuffix: +{repack_suffix}")?;
+            }
+        }
+    }
+
+    // debian/source/format
+    {
+        fs::create_dir_all(tempdir.path().join("source"))?;
+        let mut source_format = file("source/format")?;
+        writeln!(source_format, "3.0 (quilt)")?;
+    }
+
+    // debian/control & debian/tests/control
+    let (source, has_dev_depends, default_test_broken) =
+        prepare_debian_control(deb_info, crate_info, config, &mut file)?;
+
+    // for testing only, debian/debcargo_testing_bin/env
+    if testing_ignore_debpolv() {
+        fs::create_dir_all(tempdir.path().join("debcargo_testing_bin"))?;
+        let mut env_hack = file("debcargo_testing_bin/env")?;
+        #[cfg(unix)]
+        env_hack.set_permissions(fs::Permissions::from_mode(0o777))?;
+        // intercept calls to dh-cargo-built-using
+        writeln!(
+            env_hack,
+            r#"#!/bin/sh
+case "$*" in */usr/share/cargo/bin/dh-cargo-built-using*)
+echo "debcargo testing: suppressing dh-cargo-built-using";;
+*) /usr/bin/env "$@";; esac
+"#
+        )?;
+    }
+
+    // debian/rules
+    {
+        let mut rules = file("rules")?;
+        #[cfg(unix)]
+        rules.set_permissions(fs::Permissions::from_mode(0o777))?;
+        if has_dev_depends || testing_ignore_debpolv() {
+            // don't run any tests, we don't want extra B-D on dev-depends
+            // this could potentially cause B-D cycles so we avoid it
+            //
+            // also don't run crate tests during integration testing since some
+            // of them are brittle and fail; the purpose is to test debcargo
+            // not the actual crates
+            write!(
+                rules,
+                "{}",
+                concat!(
+                    "#!/usr/bin/make -f\n",
+                    "%:\n",
+                    "\tdh $@ --buildsystem cargo\n"
+                )
+            )?;
+            // some crates need nightly to compile, annoyingly. only do this in
+            // testing; outside of testing the user should explicitly override
+            // debian/rules to do this
+            if testing_ignore_debpolv() {
+                writeln!(rules, "export RUSTC_BOOTSTRAP := 1")?;
+                writeln!(
+                    rules,
+                    "export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)"
+                )?;
+            }
+        } else {
+            write!(
+                rules,
+                "{}{}",
+                concat!(
+                    "#!/usr/bin/make -f\n",
+                    "%:\n",
+                    "\tdh $@ --buildsystem cargo\n",
+                    "\n",
+                    "override_dh_auto_test:\n",
+                ),
+                // TODO: this logic is slightly brittle if another feature
+                // "provides" the default feature. In this case, you need to
+                // set test_is_broken explicitly on package."lib+default" and
+                // not package."lib+theotherfeature".
+                if default_test_broken {
+                    "\tdh_auto_test -- test --all || true\n"
+                } else {
+                    "\tdh_auto_test -- test --all\n"
+                },
+            )?;
+        }
+    }
+
+    // debian/changelog
+    if !changelog_ready {
+        let author = control::get_deb_author()?;
+        let crate_src = match config.crate_src_path(config_path) {
+            Some(_) => "local source",
+            None => "crates.io",
+        };
+        let autogenerated_item = format!(
+            "  * Package {} {} from {} using debcargo {}",
+            &crate_name,
+            &crate_version,
+            &crate_src,
+            deb_info.debcargo_version()
+        );
+        let autogenerated_re = Regex::new(&format!(
+            r"^  \* Package (.*) (.*) from {} using debcargo (.*)$",
+            &crate_src
+        ))?;
+
+        // Special-case d/changelog:
+        let (mut changelog, changelog_data) = changelog_or_new(tempdir.path())?;
+        let (changelog_old, mut changelog_items, deb_version_suffix) = {
+            let ver_bump = &|e: Option<&str>| -> Result<Option<String>> {
+                Ok(match e {
+                    Some(x) => {
+                        let e = ChangelogEntry::from_str(x)?;
+                        if e.version_parts().0 == deb_info.deb_upstream_version() {
+                            Some(e.deb_version_suffix_bump())
+                        } else {
+                            None
+                        }
+                    }
+                    None => None,
+                })
+            };
+            let mut chit = ChangelogIterator::from(&changelog_data);
+            let e1 = chit.next();
+            match e1 {
+                // If the first entry has changelog::DEFAULT_DIST then write over it smartly
+                Some(x) if x.contains(changelog::DEFAULT_DIST) => {
+                    let mut e = ChangelogEntry::from_str(x)?;
+                    if author == e.maintainer {
+                        if let Some(pos) = e.items.iter().position(|x| autogenerated_re.is_match(x))
+                        {
+                            e.items[pos] = autogenerated_item;
+                        } else {
+                            e.items.push(autogenerated_item);
+                        }
+                    } else {
+                        // If unreleased changelog is by someone else, preserve their entries
+                        e.items.insert(0, autogenerated_item);
+                        e.items.insert(1, String::new());
+                        let ename = e.maintainer_name();
+                        e.items.insert(2, format!("  [ {ename} ]"));
+                    }
+                    (&changelog_data[x.len()..], e.items, ver_bump(chit.next())?)
+                }
+                // Otherwise prepend a new entry to the existing entries
+                _ => (
+                    changelog_data.as_str(),
+                    vec![autogenerated_item],
+                    ver_bump(e1)?,
+                ),
+            }
+        };
+
+        let source_deb_version = format!(
+            "{}-{}",
+            deb_info.deb_upstream_version(),
+            &deb_version_suffix.unwrap_or_else(|| "1".to_string())
+        );
+        if !uploaders.contains(&author.as_str()) {
+            debcargo_warn!(
+                "You ({}) are not in Uploaders; adding \"Team upload\" to d/changelog",
+                author
+            );
+            if !changelog_items.contains(&changelog::COMMENT_TEAM_UPLOAD.to_string()) {
+                changelog_items.insert(0, changelog::COMMENT_TEAM_UPLOAD.to_string());
+            }
+        }
+        let changelog_new_entry = ChangelogEntry::new(
+            source.name().to_string(),
+            source_deb_version,
+            changelog::DEFAULT_DIST.to_string(),
+            "urgency=medium".to_string(),
+            author,
+            changelog::local_now(),
+            changelog_items,
+        );
+
+        changelog.seek(io::SeekFrom::Start(0))?;
+        if changelog_old.is_empty() {
+            write!(changelog, "{changelog_new_entry}")?;
+        } else {
+            write!(changelog, "{changelog_new_entry}\n{changelog_old}")?;
+        }
+        // the new file might be shorter, truncate it to the current cursor position
+        let pos = changelog.stream_position()?;
+        changelog.set_len(pos)?;
+    }
+
+    if overlay_write_back {
+        let overlay = config.overlay_dir(config_path);
+        if let Some(p) = overlay.as_ref() {
+            if !changelog_ready {
+                // Special-case d/changelog:
+                // Always write it back, this is safe because of our prepending logic
+                new_hints.push("changelog".to_string());
+            }
+            for hint in &new_hints {
+                let newpath = tempdir.path().join(hint);
+                let oldpath = p.join(hint);
+                fs::copy(newpath, oldpath).expect("could not write back");
+                debcargo_info!("Wrote back file to overlay: {}", hint);
+            }
+        }
+    }
+
+    fs::rename(tempdir.path(), output_dir.join("debian"))?;
+    Ok(())
+}
+
+fn prepare_debian_control<F: FnMut(&str) -> std::result::Result<fs::File, io::Error>>(
+    deb_info: &DebInfo,
+    crate_info: &CrateInfo,
+    config: &Config,
+    mut file: F,
+) -> Result<(Source, bool, bool)> {
+    let crate_name = crate_info.crate_name();
+    let base_pkgname = deb_info.base_package_name();
+    let name_suffix = deb_info.name_suffix();
+
+    let lib = crate_info.is_lib();
+    let mut bins = crate_info.get_binary_targets();
+    if lib && !bins.is_empty() && !config.build_bin_package() {
+        bins.clear();
+    }
+    let bin_name = if config.bin_name.eq(&Config::default().bin_name) {
+        let default_bin_name = deb_info.base_package_name();
+        if !bins.is_empty() {
+            debcargo_info!(
+                "Generate binary crate with default name '{}', set bin_name to override or bin = false to disable.",
+                &default_bin_name
+            );
+        }
+        default_bin_name
+    } else {
+        config.bin_name.as_str()
+    };
+
+    let maintainer = config.maintainer();
+    let requires_root = config.requires_root();
+    let uploaders: Vec<&str> = config
+        .uploaders()
+        .into_iter()
+        .flatten()
+        .map(String::as_str)
+        .collect();
+
+    let features_with_deps = all_dependencies_and_features(crate_info.manifest());
+    let dev_depends = deb_deps(config.allow_prerelease_deps, &crate_info.dev_dependencies())?;
+    let has_dev_deps = !dev_depends.is_empty();
+    log::trace!(
+        "features_with_deps: {:?}",
+        features_with_deps
+            .iter()
+            .map(|(&f, (ff, dd))| { (f, (ff, dd.iter().map(show_dep).collect::<Vec<_>>())) })
+            .collect::<Vec<_>>()
+    );
+    let meta = crate_info.metadata();
+
+    // debian/tests/control, preparation
+    let test_is_marked_broken = |f: &str| config.package_test_is_broken(PackageKey::feature(f));
+    let test_is_broken = |f: &str| {
+        let getparents = |f: &str| features_with_deps.get(f).map(|(d, _)| d);
+        match get_transitive_val(&getparents, &test_is_marked_broken, f) {
+            Err((k, vv)) => debcargo_bail!(
+                "{} {}: {}: {:?}",
+                "error trying to recursively determine test_is_broken for",
+                k,
+                "dependencies have inconsistent config values",
+                vv
+            ),
+            Ok(v) => Ok(v.unwrap_or(false)),
+        }
+    };
+
+    let test_architecture = |f: &str| {
+        let getparents = |f: &str| features_with_deps.get(f).map(|(d, _)| d);
+        let feature_get_test_architecture =
+            |f: &str| config.package_test_architecture(PackageKey::feature(f));
+        match get_transitive_val(&getparents, &feature_get_test_architecture, f) {
+            Err((k, vv)) => debcargo_bail!(
+                "{} {}: {}: {:?}",
+                "error trying to recursively determine test_architecture for",
+                k,
+                "dependencies have inconsistent config values",
+                vv
+            ),
+            Ok(Some(v)) if v.is_empty() => Ok(None), // allow resetting via explicit empty list
+            Ok(other) => Ok(other),
+        }
+    };
+
+    let build_deps = {
+        let mut build_deps = BuildDeps::default();
+        // these are needed for the clean target
+        build_deps.build_depends.extend(
+            ["debhelper-compat (= 13)", "dh-sequence-cargo"]
+                .iter()
+                .map(ToString::to_string),
+        );
+
+        // note: please keep this in sync with build_order::dep_features
+        let (default_features, default_deps) = transitive_deps(&features_with_deps, "default")?;
+        //debcargo_info!("default_features: {:?}", default_features);
+        //debcargo_info!("default_deps: {:?}", deb_deps(config, &default_deps)?);
+        let extra_override_deps = package_field_for_feature(
+            |x| config.package_depends(x),
+            PackageKey::feature("default"),
+            &default_features,
+        );
+        let build_deps_arch = toolchain_deps(crate_info.rust_version().as_deref())
+            .into_iter()
+            .chain(deb_deps(config.allow_prerelease_deps, &default_deps)?)
+            .chain(extra_override_deps);
+        if bins.is_empty() {
+            assert!(lib);
+            build_deps
+                .build_depends_arch
+                .extend(build_deps_arch.map(|d| {
+                    if config.skip_nocheck().unwrap_or(false) {
+                        d
+                    } else {
+                        deb_dep_add_nocheck(&d)
+                    }
+                }));
+        } else {
+            build_deps.build_depends_arch.extend(build_deps_arch);
+        }
+        build_deps
+    };
+    let test_deps: Vec<String> = Some(rustc_dep(crate_info.rust_version().as_deref(), false))
+        .into_iter()
+        .chain(dev_depends)
+        .collect();
+
+    let homepage = generate_homepage(
+        &crate_info.manifest().name(),
+        &crate_info.manifest().version().to_string(),
+        meta.homepage.as_deref(),
+        meta.repository.as_deref(),
+        config.crate_src_path.is_none(),
+    );
+
+    // no repack suffix!
+    let plain_upstream_version = control::deb_upstream_version(crate_info.version(), None);
+
+    let mut source = Source::new(
+        base_pkgname,
+        name_suffix,
+        crate_name,
+        &plain_upstream_version,
+        &homepage,
+        lib,
+        maintainer.to_string(),
+        uploaders.iter().map(ToString::to_string).collect(),
+        build_deps,
+        requires_root.cloned(),
+    )?;
+
+    // If source overrides are present update related parts.
+    source.apply_overrides(config);
+
+    let mut control = io::BufWriter::new(file("control")?);
+    write!(control, "{source}")?;
+
+    // Summary and description generated from Cargo.toml
+    let (crate_summary, crate_description) = crate_info.get_summary_description();
+    let summary_prefix = crate_summary.unwrap_or(format!("Rust crate \"{crate_name}\""));
+    let description_prefix = {
+        let tmp = crate_description.unwrap_or_default();
+        if tmp.is_empty() {
+            tmp
+        } else {
+            format!("{tmp}\n.\n")
+        }
+    };
+
+    if lib {
+        // debian/tests/control
+        let all_features: Vec<&str> = features_with_deps.keys().copied().collect();
+        let all_features_test_broken = match test_is_marked_broken("@") {
+            Some(v) => v,
+            None => all_features
+                .iter()
+                .any(|f| test_is_marked_broken(f).unwrap_or(false)),
+        };
+        let all_features_test_arch = match test_architecture("@")? {
+            Some(v) => v.to_owned(),
+            None => all_features
+                .iter()
+                .fold(HashSet::new(), |mut set, f| {
+                    if let Ok(Some(arch)) = test_architecture(f) {
+                        set.extend(arch.to_owned());
+                    }
+                    set
+                })
+                .into_iter()
+                .collect_vec(),
+        };
+        let all_features_test_arch: Vec<&str> =
+            all_features_test_arch.iter().map(AsRef::as_ref).collect();
+        let all_features_test_depends =
+            generate_test_dependencies("@", &all_features, config, &test_deps);
+        let mut testctl = io::BufWriter::new(file("tests/control")?);
+        write!(
+            testctl,
+            "{}",
+            PkgTest::new(
+                source.name(),
+                crate_name,
+                "@",
+                &plain_upstream_version,
+                &["--all-features"],
+                &all_features_test_depends,
+                if all_features_test_broken {
+                    &["flaky"]
+                } else {
+                    &[]
+                },
+                &all_features_test_arch,
+            )?
+        )?;
+
+        // begin transforming dependencies
+        let working_features_with_deps = features_with_deps.clone();
+        let working_features_with_deps = {
+            let mut working_features_with_deps = working_features_with_deps;
+            // Detect corner case with feature naming regarding _ vs -.
+            // Debian does not support _ in package names. Cargo automatically
+            // converts - in crate names to _, but features (including optional
+            // dependencies) can have both _ and -.
+            let potential_corner_case = working_features_with_deps
+                .keys()
+                .filter(|x| base_deb_name(x).as_str() != **x)
+                .copied()
+                .collect::<Vec<_>>();
+            for f in potential_corner_case {
+                let f_ = base_deb_name(f);
+                if let Some((df1, dd1)) = working_features_with_deps.remove(f_.as_str()) {
+                    // merge dependencies of f_ and f
+                    working_features_with_deps
+                        .entry(f)
+                        .and_modify(|(df0, dd0)| {
+                            let mut df = BTreeSet::from_iter(df0.drain(..));
+                            df.extend(df1);
+                            df.remove(f_.as_str());
+                            df.remove(f);
+                            let mut dd: HashSet<cargo::core::Dependency> =
+                                HashSet::from_iter(dd0.drain(..));
+                            dd.extend(dd1);
+                            df0.extend(df);
+                            dd0.extend(dd);
+                        });
+                    // go through other feature deps and change f_ to f
+                    for (df, _) in &mut working_features_with_deps.values_mut() {
+                        for feat in df.iter_mut() {
+                            if *feat == f_.as_str() {
+                                *feat = f;
+                            }
+                        }
+                    }
+                    // check we didn't create a cycle in features
+                    let dep_feats = traverse_depth(
+                        &|k: &&'static str| working_features_with_deps.get(k).map(|x| &x.0),
+                        f,
+                    );
+                    if dep_feats.contains(f) {
+                        log::debug!("transitive deps of feature {f}: {dep_feats:?}");
+                        debcargo_bail!(
+                            "Tried to merge features {} and {} as they are not representable separately\n\
+                             in Debian, but this resulted in a feature cycle. You need to manually patch the package.", f, f_);
+                    }
+                    debcargo_warn!(
+                        "Merged features {} and {} as they are not representable separately in Debian.\n\
+                         We checked that this does not break the package in an obvious way (feature cycle), however\n\
+                         if there is a more sophisticated breakage, you'll have to manually patch those \
+                         features instead.", f, f_);
+                }
+            }
+            working_features_with_deps
+        };
+        log::trace!(
+            "working_features_with_deps: {:?}",
+            working_features_with_deps
+                .iter()
+                .map(|(&f, (ff, dd))| { (f, (ff, dd.iter().map(show_dep).collect::<Vec<_>>())) })
+                .collect::<Vec<_>>()
+        );
+        let (mut provides, reduced_features_with_deps) = if config.collapse_features {
+            collapse_features(&working_features_with_deps)
+        } else {
+            reduce_provides(working_features_with_deps)
+        };
+        log::trace!(
+            "reduced_features_with_deps: {:?}",
+            reduced_features_with_deps
+                .iter()
+                .map(|(&f, (ff, dd))| { (f, (ff, dd.iter().map(show_dep).collect::<Vec<_>>())) })
+                .collect::<Vec<_>>()
+        );
+        // end transforming dependencies
+
+        log::trace!("provides: {provides:?}");
+        let mut recommends = vec![];
+        let mut suggests = vec![];
+        for (&feature, features) in &provides {
+            if feature.is_empty() {
+                continue;
+            } else if feature == "default" || features.contains(&"default") {
+                recommends.push(feature);
+            } else {
+                suggests.push(feature);
+            }
+        }
+
+        let mut no_features_edge_case = BTreeMap::new();
+        no_features_edge_case.insert("", (vec![], vec![]));
+        no_features_edge_case.insert("default", (vec![""], vec![]));
+        let no_features_edge_case = features_with_deps == no_features_edge_case;
+
+        for (feature, (f_deps, o_deps)) in reduced_features_with_deps {
+            let pk = PackageKey::feature(feature);
+            let f_provides = provides.remove(feature).unwrap();
+            let mut crate_features = f_provides.clone();
+            crate_features.push(feature);
+
+            let summary_suffix = if feature.is_empty() {
+                " - Rust source code".to_string()
+            } else {
+                match f_provides.len() {
+                    0 => format!(" - feature \"{feature}\""),
+                    _ => format!(" - feature \"{}\" and {} more", feature, f_provides.len()),
+                }
+            };
+            let description_suffix = if feature.is_empty() {
+                format!("Source code for Debianized Rust crate \"{crate_name}\"")
+            } else {
+                format!(
+                    "This metapackage enables feature \"{}\" for the \
+                     Rust {} crate, by pulling in any additional \
+                     dependencies needed by that feature.{}",
+                    feature,
+                    crate_name,
+                    match f_provides.len() {
+                        0 => String::new(),
+                        1 => format!(
+                            "\n\nAdditionally, this package also provides the \
+                             \"{}\" feature.",
+                            f_provides[0],
+                        ),
+                        _ => format!(
+                            "\n\nAdditionally, this package also provides the \
+                             \"{}\", and \"{}\" features.",
+                            f_provides[..f_provides.len() - 1].join("\", \""),
+                            f_provides[f_provides.len() - 1],
+                        ),
+                    },
+                )
+            };
+            let mut package = Package::new(
+                base_pkgname,
+                name_suffix,
+                crate_info.version(),
+                Description {
+                    prefix: summary_prefix.clone(),
+                    suffix: summary_suffix.clone(),
+                },
+                Description {
+                    prefix: description_prefix.clone(),
+                    suffix: description_suffix.clone(),
+                },
+                if feature.is_empty() {
+                    None
+                } else {
+                    Some(feature)
+                },
+                &f_deps,
+                deb_deps(config.allow_prerelease_deps, &o_deps)?,
+                &f_provides.clone(),
+                if feature.is_empty() { &recommends } else { &[] },
+                if feature.is_empty() { &suggests } else { &[] },
+            )?;
+            // If any overrides present for this package it will be taken care.
+            package.apply_overrides(config, pk, &f_provides);
+
+            if package.summary_check_len().is_err() {
+                writeln!(
+                    control,
+                    concat!(
+                        "\n",
+                        "# FIXME (packages.\"(name)\".section) debcargo ",
+                        "auto-generated summary for {} is very long, consider overriding"
+                    ),
+                    package.name(),
+                )?;
+            }
+
+            write!(control, "\n{package}")?;
+
+            // Override pointless overzealous warnings from lintian
+            if !feature.is_empty() {
+                let mut overrides =
+                    io::BufWriter::new(file(&format!("{}.lintian-overrides", package.name()))?);
+                write!(
+                    overrides,
+                    "{} binary: empty-rust-library-declares-provides *",
+                    package.name()
+                )?;
+            }
+
+            // Generate tests for all features in this package
+            if !no_features_edge_case {
+                for f in crate_features {
+                    let (feature_deps, _) = transitive_deps(&features_with_deps, f)?;
+
+                    // args
+                    let mut args = if f == "default" || feature_deps.contains(&"default") {
+                        vec![]
+                    } else {
+                        vec!["--no-default-features"]
+                    };
+                    // --features default sometimes fails, see
+                    // https://github.com/rust-lang/cargo/issues/8164
+                    if !f.is_empty() && f != "default" {
+                        args.push("--features");
+                        args.push(f);
+                    }
+
+                    // deps
+                    let test_depends =
+                        generate_test_dependencies(f, &feature_deps, config, &test_deps);
+                    let test_arch = match test_architecture(f)? {
+                        Some(v) => v.to_owned(),
+                        None => Vec::new(),
+                    };
+                    let test_arch: Vec<&str> = test_arch.iter().map(AsRef::as_ref).collect();
+                    let pkgtest = PkgTest::new(
+                        package.name(),
+                        crate_name,
+                        f,
+                        &plain_upstream_version,
+                        &args,
+                        &test_depends,
+                        if test_is_broken(f)? { &["flaky"] } else { &[] },
+                        &test_arch,
+                    )?;
+                    write!(testctl, "\n{pkgtest}")?;
+                }
+            }
+        }
+        assert!(provides.is_empty());
+        // reduced_features_with_deps consumed by into_iter, no longer usable
+    }
+
+    if !bins.is_empty() {
+        // adding " - binaries" is a bit redundant for users, so just leave as-is
+        let summary_suffix = String::new();
+        let description_suffix = format!(
+            "This package contains the following binaries built from the Rust crate\n\"{}\":\n - {}",
+            crate_name,
+            bins.join("\n - ")
+        );
+
+        let mut bin_pkg = Package::new_bin(
+            bin_name,
+            name_suffix,
+            // if not-a-lib then Source section is already FIXME
+            if lib {
+                Some("FIXME-(packages.\"(name)\".section)")
+            } else {
+                None
+            },
+            Description {
+                prefix: summary_prefix,
+                suffix: summary_suffix,
+            },
+            Description {
+                prefix: description_prefix,
+                suffix: description_suffix,
+            },
+        );
+
+        // Binary package overrides.
+        bin_pkg.apply_overrides(config, PackageKey::Bin, &[]);
+        write!(control, "\n{bin_pkg}")?;
+    }
+
+    for configured in config.configured_packages() {
+        if let PackageKey::Extra(package) = configured {
+            let mut extra_pkg = Package::new_extra(package.to_string());
+            extra_pkg.apply_overrides(config, configured, &[]);
+            write!(control, "\n{extra_pkg}")?;
+        }
+    }
+
+    Ok((source, has_dev_deps, test_is_broken("default")?))
+}
+
+fn generate_homepage(
+    name: &str,
+    version: &str,
+    homepage: Option<&str>,
+    repository: Option<&str>,
+    on_crates_io: bool,
+) -> String {
+    let fallback = if on_crates_io {
+        format!("https://crates.io/crates/{name}/{version}",)
+    } else {
+        String::new()
+    };
+
+    // prefer Cargo.toml homepage, fallback to Cargo.toml repository, or crates.io page as a last
+    // resort
+    homepage.or(repository).unwrap_or(&fallback).to_owned()
+}
+
+fn generate_test_dependencies(
+    f: &str,
+    feature_deps: &[&str],
+    config: &Config,
+    test_deps: &[String],
+) -> Vec<String> {
+    Some(f)
+        .iter()
+        .chain(feature_deps)
+        .flat_map(|f| {
+            config
+                .package_test_depends(PackageKey::feature(f))
+                .into_iter()
+                .flatten()
+        })
+        .map(ToString::to_string)
+        .chain(test_deps.to_owned())
+        .collect::<Vec<_>>()
+}
+
+fn collapse_features(
+    orig_features_with_deps: &CrateDepInfo,
+) -> (BTreeMap<&'static str, Vec<&'static str>>, CrateDepInfo) {
+    let (provides, deps) = orig_features_with_deps.iter().fold(
+        (Vec::new(), Vec::new()),
+        |(mut provides, mut deps), (f, (_, f_deps))| {
+            if f != &"" {
+                provides.push(*f);
+            }
+            deps.append(&mut f_deps.clone());
+            (provides, deps)
+        },
+    );
+
+    let mut collapsed_provides = BTreeMap::new();
+    collapsed_provides.insert("", provides);
+
+    let mut collapsed_features_with_deps = BTreeMap::new();
+    collapsed_features_with_deps.insert("", (Vec::new(), deps));
+
+    (collapsed_provides, collapsed_features_with_deps)
+}
+
+/// Calculate Provides: in an attempt to reduce the number of binaries.
+///
+/// The algorithm is very simple and incomplete. e.g. it does not, yet
+/// simplify things like:
+///   f1 depends on f2, f3
+///   f2 depends on f4
+///   f3 depends on f4
+/// into
+///   f4 provides f1, f2, f3
+fn reduce_provides(
+    mut features_with_deps: CrateDepInfo,
+) -> (BTreeMap<&'static str, Vec<&'static str>>, CrateDepInfo) {
+    // If any features have duplicate dependencies, deduplicate them by
+    // making all the subsequent ones depend on the first one.
+    let mut features_rev_deps = HashMap::new();
+    for (&f, dep) in &features_with_deps {
+        if !features_rev_deps.contains_key(dep) {
+            features_rev_deps.insert(dep.clone(), vec![]);
+        }
+        features_rev_deps.get_mut(dep).unwrap().push(f);
+    }
+    for (_, ff) in features_rev_deps {
+        let f0 = ff[0];
+        for f in &ff[1..] {
+            features_with_deps.insert(f, (vec![f0], vec![]));
+        }
+    }
+
+    // Calculate provides by following 0- or 1-length dependency lists.
+    let mut provides = BTreeMap::new();
+    let mut provided = Vec::new();
+    for (&f, (ref ff, ref dd)) in &features_with_deps {
+        //debcargo_info!("provides considering: {:?}", &f);
+        if !dd.is_empty() {
+            continue;
+        }
+        assert!(!ff.is_empty() || f.is_empty());
+        let k = if ff.len() == 1 {
+            // if A depends on a single feature B, then B provides A.
+            ff[0]
+        } else {
+            continue;
+        };
+        //debcargo_info!("provides still considering: {:?}", &f);
+        if !provides.contains_key(k) {
+            provides.insert(k, vec![]);
+        }
+        provides.get_mut(k).unwrap().push(f);
+        provided.push(f);
+    }
+
+    //debcargo_info!("provides-internal: {:?}", &provides);
+    //debcargo_info!("provided-internal: {:?}", &provided);
+    for p in provided {
+        features_with_deps.remove(p);
+    }
+
+    let provides = features_with_deps
+        .keys()
+        .map(|k| {
+            (
+                *k,
+                traverse_depth(&|k: &&'static str| provides.get(k), k)
+                    .into_iter()
+                    .collect::<Vec<_>>(),
+            )
+        })
+        .collect::<BTreeMap<_, _>>();
+
+    (provides, features_with_deps)
+}
+
+pub(crate) fn toolchain_deps(min_rust_version: Option<&str>) -> Vec<String> {
+    let rustc = rustc_dep(min_rust_version, true);
+    // libstd-rust-dev here is needed to pick up the right arch variant for cross-builds!
+    ["cargo:native".into(), rustc, "libstd-rust-dev".into()].into()
+}
+
+fn rustc_dep(min_ver: Option<&str>, native: bool) -> String {
+    let native = if native { ":native" } else { "" };
+    if let Some(min_ver) = min_ver {
+        format!("rustc{native} (>= {min_ver})")
+    } else {
+        format!("rustc{native}")
+    }
+}
+
+fn changelog_or_new(tempdir: &Path) -> Result<(fs::File, String)> {
+    let mut changelog = fs::OpenOptions::new()
+        .read(true)
+        .write(true)
+        .create(true)
+        .truncate(false)
+        .open(tempdir.join("changelog"))?;
+    let mut changelog_data = String::new();
+    changelog.read_to_string(&mut changelog_data)?;
+    Ok((changelog, changelog_data))
+}
+
+fn changelog_first_last(tempdir: &Path) -> Result<(i32, i32)> {
+    let mut changelog = fs::File::open(tempdir.join("changelog"))?;
+    let mut changelog_data = String::new();
+    changelog.read_to_string(&mut changelog_data)?;
+    let mut last = None;
+    let mut first = None;
+    for x in ChangelogIterator::from(&changelog_data) {
+        let e = ChangelogEntry::from_str(x)?;
+        if last.is_none() {
+            last = Some(e.date.year());
+        }
+        first = Some(e.date.year());
+    }
+    if let Some(last) = last {
+        Ok((first.unwrap(), last))
+    } else {
+        Err(format_err!("changelog had no entries"))
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::{generate_homepage, rustc_dep};
+
+    #[test]
+    fn rustc_dep_includes_minver() {
+        assert_eq!("rustc:native (>= 1.65)", rustc_dep(Some("1.65"), true));
+    }
+
+    #[test]
+    fn rustc_dep_excludes_minver() {
+        assert_eq!("rustc:native", rustc_dep(None, true));
+    }
+
+    #[test]
+    fn rustc_dep_includes_minver_autopkgtest() {
+        assert_eq!("rustc (>= 1.65)", rustc_dep(Some("1.65"), false));
+    }
+
+    #[test]
+    fn rustc_dep_excludes_minver_autopkgtest() {
+        assert_eq!("rustc", rustc_dep(None, false));
+    }
+
+    #[test]
+    fn homepage_is_homepage() {
+        assert_eq!(
+            "https://example.com",
+            generate_homepage(
+                "crate",
+                "1.0".into(),
+                Some("https://example.com"),
+                Some("https://example.com/repo"),
+                true
+            )
+        );
+
+        assert_eq!(
+            "https://example.com",
+            generate_homepage(
+                "crate",
+                "1.0".into(),
+                Some("https://example.com"),
+                None,
+                true
+            )
+        );
+
+        assert_eq!(
+            "https://example.com",
+            generate_homepage(
+                "crate",
+                "1.0".into(),
+                Some("https://example.com"),
+                Some("https://example.com/repo"),
+                false
+            )
+        );
+
+        assert_eq!(
+            "https://example.com",
+            generate_homepage(
+                "crate",
+                "1.0".into(),
+                Some("https://example.com"),
+                None,
+                false
+            )
+        );
+    }
+
+    #[test]
+    fn homepage_is_repository() {
+        assert_eq!(
+            "https://example.com/repo",
+            generate_homepage(
+                "crate",
+                "1.0".into(),
+                None,
+                Some("https://example.com/repo"),
+                true
+            )
+        );
+
+        assert_eq!(
+            "https://example.com/repo",
+            generate_homepage(
+                "crate",
+                "1.0".into(),
+                None,
+                Some("https://example.com/repo"),
+                true
+            )
+        );
+
+        assert_eq!(
+            "https://example.com/repo",
+            generate_homepage(
+                "crate",
+                "1.0".into(),
+                None,
+                Some("https://example.com/repo"),
+                false
+            )
+        );
+
+        assert_eq!(
+            "https://example.com/repo",
+            generate_homepage(
+                "crate",
+                "1.0".into(),
+                None,
+                Some("https://example.com/repo"),
+                false
+            )
+        );
+    }
+
+    #[test]
+    fn homepage_is_fallback() {
+        assert_eq!(
+            "https://crates.io/crates/crate/1.0",
+            generate_homepage("crate", "1.0".into(), None, None, true)
+        );
+
+        assert_eq!(
+            "",
+            generate_homepage("crate", "1.0".into(), None, None, false)
+        );
+    }
+}
diff --git a/src/errors.rs b/src/errors.rs
new file mode 100644 (file)
index 0000000..8e2281e
--- /dev/null
@@ -0,0 +1,55 @@
+use anyhow;
+
+pub type Result<T> = std::result::Result<T, anyhow::Error>;
+pub use anyhow::format_err;
+
+#[macro_export]
+macro_rules! debcargo_info {
+    ($e:expr) => {
+        {
+            use nu_ansi_term::Color::Green;
+            eprintln!("{}", Green.paint($e));
+        }
+    };
+
+    ($fmt:expr, $( $arg:tt)+) => {
+        {
+            use nu_ansi_term::Color::Green;
+            let print_string = format!($fmt, $($arg)+);
+            eprintln!("{}", Green.paint(print_string));
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! debcargo_warn {
+    ($e:expr) => {
+        {
+            use nu_ansi_term::Color::Rgb;
+            eprintln!("{}", Rgb(255,165,0).bold().paint($e));
+        }
+    };
+
+    ($fmt:expr, $( $arg:tt)+) => {
+        {
+            use nu_ansi_term::Color::Rgb;
+            let print_string = Rgb(255,165,0).bold().paint(format!($fmt, $($arg)+));
+            eprintln!("{}", print_string);
+        }
+    };
+
+}
+
+#[macro_export]
+macro_rules! debcargo_bail {
+    ($e:expr) => {{
+        return Err(::anyhow::format_err!("{}", $e));
+    }};
+
+    ($fmt:expr, $( $arg:tt)+) => {
+        {
+            let error_string = format!($fmt, $($arg)+);
+            return Err(::anyhow::format_err!("{}", error_string));
+        }
+    };
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644 (file)
index 0000000..104ef4e
--- /dev/null
@@ -0,0 +1,13 @@
+#[macro_use]
+pub mod errors;
+pub mod cli;
+pub mod config;
+pub mod crates;
+pub mod debian;
+mod util;
+
+pub mod build_order;
+pub mod deb_dependencies;
+pub mod package;
+#[cfg(feature = "update-dependencies")]
+pub mod update_dependencies;
diff --git a/src/package.rs b/src/package.rs
new file mode 100644 (file)
index 0000000..1d51024
--- /dev/null
@@ -0,0 +1,282 @@
+use std::path::PathBuf;
+
+use anyhow::Context;
+
+use clap::{crate_version, Parser};
+
+use crate::config::{Config, PackageKey};
+use crate::crates::CrateInfo;
+use crate::debian::{self, DebInfo};
+use crate::errors::Result;
+use crate::util;
+
+pub struct PackageProcess {
+    // below state is filled in during init
+    pub crate_info: CrateInfo,
+    pub deb_info: DebInfo,
+    pub config_path: Option<PathBuf>,
+    pub config: Config,
+    // below state is filled in during the process
+    /// Output directory as specified by the user.
+    pub output_dir: Option<PathBuf>,
+    /// Whether the crate tarball was modified, and whether that included Cargo.toml
+    /// (re)normalization
+    pub source_modified: bool,
+    /// If it was modified, whether that included Cargo.toml normalization
+    pub manifest_normalized: bool,
+    /// Tempdir that contains a working copy of the eventual output.
+    pub temp_output_dir: Option<tempfile::TempDir>,
+    pub orig_tarball: Option<PathBuf>,
+}
+
+#[derive(Debug, Clone, Parser)]
+pub struct PackageInitArgs {
+    /// Name of the crate to package.
+    pub crate_name: String,
+    /// Version of the crate to package; may contain dependency operators.
+    /// If empty string or omitted, resolves to the latest version.
+    pub version: Option<String>,
+    /// TOML file providing package-specific options.
+    #[arg(long)]
+    pub config: Option<PathBuf>,
+}
+
+#[derive(Debug, Clone, Parser)]
+pub struct PackageExtractArgs {
+    /// Output directory for the package. The orig tarball is named according
+    /// to Debian conventions in the parent directory of this directory.
+    #[arg(long)]
+    pub directory: Option<PathBuf>,
+}
+
+#[derive(Debug, Clone, Parser)]
+pub struct PackageExecuteArgs {
+    /// Assume the changelog is already bumped, and leave it alone.
+    #[arg(long)]
+    pub changelog_ready: bool,
+    /// Guess extra values for d/copyright. Might be slow.
+    #[arg(long)]
+    pub copyright_guess_harder: bool,
+    /// Don't write back hint files or d/changelog to the source overlay directory.
+    #[arg(long)]
+    pub no_overlay_write_back: bool,
+}
+
+impl PackageProcess {
+    /// More fine-grained access. For normal usage see `Self::init` instead.
+    pub fn new(
+        mut crate_info: CrateInfo,
+        config_path: Option<PathBuf>,
+        config: Config,
+    ) -> Result<Self> {
+        crate_info.set_includes_excludes(config.orig_tar_excludes(), config.orig_tar_whitelist());
+        let deb_info = DebInfo::new(
+            &crate_info,
+            crate_version!(),
+            config.semver_suffix,
+            config.repack_suffix(),
+        );
+
+        Ok(Self {
+            crate_info,
+            deb_info,
+            config_path,
+            config,
+            output_dir: None,
+            source_modified: false,
+            manifest_normalized: false,
+            temp_output_dir: None,
+            orig_tarball: None,
+        })
+    }
+
+    pub fn init(init_args: PackageInitArgs) -> Result<Self> {
+        let crate_name = &init_args.crate_name;
+        let version = init_args.version.as_deref();
+        let config = init_args.config;
+
+        let (config_path, config) = match config {
+            Some(path) => {
+                let config = Config::parse(&path).context("failed to parse debcargo.toml")?;
+                (Some(path), config)
+            }
+            None => (None, Config::default()),
+        };
+
+        let crate_path = config.crate_src_path(config_path.as_deref());
+        let crate_info = match crate_path {
+            Some(p) => CrateInfo::new_with_local_crate(crate_name, version, &p)?,
+            None => CrateInfo::new(crate_name, version)?,
+        };
+
+        Self::new(crate_info, config_path, config)
+    }
+
+    pub fn extract(&mut self, extract: PackageExtractArgs) -> Result<()> {
+        assert!(self.output_dir.is_none());
+        let Self {
+            crate_info,
+            deb_info,
+            ..
+        } = self;
+        // vars read; begin stage
+
+        let output_dir = extract
+            .directory
+            .unwrap_or_else(|| deb_info.package_source_dir().to_path_buf());
+
+        let (source_modified, manifest_normalized) = crate_info.extract_crate(&output_dir)?;
+
+        if source_modified && self.config.repack_suffix().is_none() {
+            debcargo_bail!("orig tarball has been modified, but no repack_suffix set -> please set repack_suffix in debcargo.toml!");
+        }
+
+        // stage finished; set vars
+        self.output_dir = Some(output_dir);
+        self.source_modified = source_modified;
+        self.manifest_normalized = manifest_normalized;
+        Ok(())
+    }
+
+    pub fn apply_overrides(&mut self) -> Result<()> {
+        assert!(self.temp_output_dir.is_none());
+        let Self {
+            crate_info,
+            config_path,
+            config,
+            output_dir,
+            ..
+        } = self;
+        let output_dir = output_dir.as_ref().unwrap();
+        // vars read; begin stage
+
+        let temp_output_dir = debian::apply_overlay_and_patches(
+            crate_info,
+            config_path.as_deref(),
+            config,
+            output_dir,
+        )?;
+
+        // stage finished; set vars
+        self.temp_output_dir = Some(temp_output_dir);
+        Ok(())
+    }
+
+    pub fn prepare_orig_tarball(&mut self) -> Result<()> {
+        assert!(self.orig_tarball.is_none());
+        let Self {
+            crate_info,
+            deb_info,
+            output_dir,
+            source_modified,
+            manifest_normalized,
+            ..
+        } = self;
+        let output_dir = output_dir.as_ref().unwrap();
+        // vars read; begin stage
+
+        let orig_tarball = output_dir
+            .parent()
+            .unwrap()
+            .join(deb_info.orig_tarball_path());
+        debian::prepare_orig_tarball(
+            crate_info,
+            &orig_tarball,
+            *source_modified,
+            *manifest_normalized,
+            output_dir,
+        )?;
+
+        // stage finished; set vars
+        self.orig_tarball = Some(orig_tarball);
+        Ok(())
+    }
+
+    pub fn prepare_debian_folder(&mut self, args: &PackageExecuteArgs) -> Result<()> {
+        let Self {
+            crate_info,
+            deb_info,
+            config_path,
+            config,
+            output_dir,
+            temp_output_dir,
+            ..
+        } = self;
+        let output_dir = output_dir.as_ref().unwrap();
+        let temp_output_dir = temp_output_dir.as_ref().unwrap();
+        // vars read; begin stage
+
+        debian::prepare_debian_folder(
+            crate_info,
+            deb_info,
+            config_path.as_deref(),
+            config,
+            output_dir,
+            temp_output_dir,
+            args.changelog_ready,
+            args.copyright_guess_harder,
+            !args.no_overlay_write_back,
+        )?;
+
+        // stage finished; set vars
+        Ok(())
+    }
+
+    pub fn post_package_checks(&self) -> Result<()> {
+        let Self {
+            config_path,
+            config,
+            output_dir,
+            orig_tarball,
+            ..
+        } = self;
+        let output_dir = output_dir.as_ref().unwrap();
+        let orig_tarball = orig_tarball.as_ref().unwrap();
+
+        let curdir = std::env::current_dir()?;
+        debcargo_info!(
+            concat!("Package Source: {}\n", "Original Tarball for package: {}\n"),
+            util::rel_p(output_dir, &curdir),
+            util::rel_p(orig_tarball, &curdir)
+        );
+        let fixmes = util::lookup_fixmes(output_dir)?;
+        if !fixmes.is_empty() {
+            debcargo_warn!("FIXME found in the following files.");
+            for f in fixmes {
+                if util::hint_file_for(&f).is_some() {
+                    debcargo_warn!("\t(•) {}", util::rel_p(&f, &curdir));
+                } else {
+                    debcargo_warn!("\t •  {}", util::rel_p(&f, &curdir));
+                }
+            }
+            debcargo_warn!("");
+            debcargo_warn!("To fix, try combinations of the following: ");
+            match config_path.as_deref() {
+                None => debcargo_warn!("\t •  Write a config file and use it with --config"),
+                Some(c) => {
+                    debcargo_warn!("\t •  Add or edit overrides in your config file:");
+                    debcargo_warn!("\t    {}", util::rel_p(c, &curdir));
+                }
+            }
+            match config.overlay_dir(config_path.as_deref()) {
+                None => debcargo_warn!("\t •  Create an overlay directory and add it to your config file with overlay = \"/path/to/overlay\""),
+                Some(p) => {
+                    debcargo_warn!("\t •  Add or edit files in your overlay directory:");
+                    debcargo_warn!("\t    {}", util::rel_p(&p, &curdir));
+                }
+            }
+        }
+        if let Some(architecture) = self.config.package_architecture(PackageKey::BareLib) {
+            if architecture == &vec!["all"] {
+                debcargo_warn!("");
+                debcargo_warn!(
+                    "'Architecture: all' override found for library package. This potentially breaks Multi-Arch,"
+                );
+                debcargo_warn!(
+                    "see https://rust-team.pages.debian.net/book/policy.html#why-architecture-any."
+                );
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/src/update_dependencies.rs b/src/update_dependencies.rs
new file mode 100644 (file)
index 0000000..278ba31
--- /dev/null
@@ -0,0 +1,429 @@
+use anyhow::{Context, Result};
+use clap::Parser;
+use regex::Regex;
+use std::collections::{BTreeSet, HashSet};
+use std::path::PathBuf;
+
+use cargo::core::Workspace;
+use cargo::GlobalContext;
+
+use debian_control::lossless::control::Control;
+use debian_control::lossless::relations::Entry;
+
+use crate::deb_dependencies::get_deb_dependencies;
+use crate::debcargo_info;
+use crate::debian::control::{base_deb_name, Package, DEV_SUFFIX};
+
+#[derive(Debug, Clone, Parser)]
+pub struct UpdateDependenciesArgs {
+    /// Drop Rust development package dependencies that are not referenced by any workspace crate
+    #[clap(long)]
+    drop_unreferenced: bool,
+
+    /// Include dependencies for crates that are present as workspace members
+    #[clap(long)]
+    include_local_crates: bool,
+
+    /// Features to include in dependencies (can be specified multiple times)
+    #[clap(long)]
+    features: Vec<String>,
+
+    /// Include all features in dependencies
+    #[clap(long)]
+    all_features: bool,
+
+    /// Do not include default feature in dependencies
+    #[clap(long)]
+    no_default_features: bool,
+
+    /// Allow prerelease versions of dependencies
+    #[clap(long)]
+    allow_prerelease_deps: bool,
+
+    /// Include dev-dependencies
+    #[clap(long)]
+    include_dev_dependencies: bool,
+}
+
+/// Discover all Cargo.toml files for workspace crates.
+///
+/// Uses cargo's Workspace API to find all workspace member crates.
+fn discover_workspace_crates() -> Result<(Vec<PathBuf>, HashSet<String>)> {
+    let gctx = GlobalContext::default()?;
+    let root_manifest = std::env::current_dir()?.join("Cargo.toml");
+    let workspace = Workspace::new(&root_manifest, &gctx)?;
+
+    let manifest_paths: Vec<PathBuf> = workspace
+        .members()
+        .map(|pkg| pkg.manifest_path().to_path_buf())
+        .collect();
+
+    let crate_names: HashSet<String> = workspace
+        .members()
+        .map(|pkg| pkg.name().to_string())
+        .collect();
+
+    Ok((manifest_paths, crate_names))
+}
+
+/// Check if a package name matches a local crate.
+///
+/// Uses a regex pattern to match package names like:
+/// - librust-foo-dev (exact match)
+/// - librust-foo-0.1-dev (versioned)
+/// - librust-foo+feature-dev (feature variant)
+/// - librust-foo-0.1+feature-dev (versioned with feature)
+///
+/// The regex pattern is:
+/// librust-{crate_name}(?:-([0-9]+(?:\.[0-9]+(?:\.[0-9]+)?)?)?)?(\+[0-9a-zA-Z-]+)??-dev
+fn is_local_package(pkg_name: &str, crate_name: &str) -> bool {
+    // Build regex pattern for this crate name
+    let pattern = format!(
+        r"^librust-{crate_name}(?:-([0-9]+(?:\.[0-9]+(?:\.[0-9]+)?)?)?)?(\+[0-9a-zA-Z-]+)?-dev$"
+    );
+
+    // Safe to unwrap since we control the pattern
+    let re = Regex::new(&pattern).unwrap();
+    re.is_match(pkg_name)
+}
+
+/// Filter out dependencies that correspond to local workspace crates
+fn filter_local_crate_dependencies(
+    deps: &BTreeSet<String>,
+    local_crate_names: &HashSet<String>,
+) -> BTreeSet<String> {
+    // Convert crate names to Debian format (underscores -> hyphens)
+    let local_deb_names: HashSet<String> = local_crate_names
+        .iter()
+        .map(|name| base_deb_name(name))
+        .collect();
+
+    let mut filtered_deps = BTreeSet::new();
+
+    for dep in deps {
+        // Parse the dependency string using debian_control
+        let entry: Entry = if let Ok(e) = dep.parse() {
+            e
+        } else {
+            // If parsing fails, keep the dependency
+            filtered_deps.insert(dep.clone());
+            continue;
+        };
+
+        // Check if any relation in this entry refers to a local crate
+        let is_local = entry.relations().any(|rel| {
+            let pkg_name = rel.name();
+            local_deb_names
+                .iter()
+                .any(|crate_name| is_local_package(&pkg_name, crate_name))
+        });
+
+        if is_local {
+            debcargo_info!("  Excluding local crate: {}", dep);
+        } else {
+            filtered_deps.insert(dep.clone());
+        }
+    }
+
+    filtered_deps
+}
+
+/// Update Build-Depends field in debian/control
+fn update_build_dependencies(
+    control_path: &str,
+    new_deps: &BTreeSet<String>,
+    drop_unreferenced: bool,
+) -> Result<()> {
+    let control = Control::from_file(control_path).context("Failed to read debian/control")?;
+
+    let mut source = control.source().context("No source paragraph found")?;
+
+    // Get or create Build-Depends
+    let mut build_depends = source
+        .build_depends()
+        .unwrap_or_else(debian_control::lossless::relations::Relations::new);
+
+    // Get package names from new_deps for quick lookup
+    let new_pkg_names: HashSet<String> = new_deps
+        .iter()
+        .filter_map(|dep| dep.parse::<Entry>().ok())
+        .flat_map(|entry| entry.relations().map(|rel| rel.name()).collect::<Vec<_>>())
+        .collect();
+
+    // Drop unreferenced librust-*-dev packages if requested
+    let mut dropped_count = 0;
+    if drop_unreferenced {
+        let pkg_prefix = Package::pkg_prefix();
+        let to_drop: Vec<String> = build_depends
+            .entries()
+            .flat_map(|entry| entry.relations().map(|rel| rel.name()).collect::<Vec<_>>())
+            .filter(|pkg_name| {
+                pkg_name.starts_with(pkg_prefix)
+                    && pkg_name.ends_with(DEV_SUFFIX)
+                    && !new_pkg_names.contains(pkg_name)
+            })
+            .collect();
+
+        for pkg in &to_drop {
+            if build_depends.drop_dependency(pkg) {
+                debcargo_info!("  Dropping: {}", pkg);
+                dropped_count += 1;
+            }
+        }
+    }
+
+    // Add/ensure new dependencies using ensure_relation
+    let mut added_count = 0;
+    for dep in new_deps {
+        let entry: Entry = dep
+            .parse()
+            .map_err(|e| anyhow::anyhow!("Failed to parse dependency '{dep}': {e}"))?;
+
+        if build_depends.ensure_relation(entry) {
+            debcargo_info!("  Adding: {}", dep);
+            added_count += 1;
+        }
+    }
+
+    // Update the Build-Depends field
+    source.set_build_depends(&build_depends);
+
+    // Write the updated control file
+    std::fs::write(control_path, control.to_string()).context("Failed to write debian/control")?;
+
+    if dropped_count > 0 {
+        debcargo_info!(
+            "\nDropped {} unreferenced {}*{} dependencies",
+            dropped_count,
+            Package::pkg_prefix(),
+            DEV_SUFFIX
+        );
+    }
+    debcargo_info!("Added {} new build dependencies", added_count);
+
+    Ok(())
+}
+
+pub fn update_dependencies(args: &UpdateDependenciesArgs) -> Result<()> {
+    let control_path = "debian/control";
+
+    // Discover all workspace crates
+    debcargo_info!("Discovering workspace crates...");
+    let (crate_manifests, crate_names) = discover_workspace_crates()?;
+    debcargo_info!("Found {} workspace crates:", crate_manifests.len());
+    for manifest in &crate_manifests {
+        debcargo_info!("  - {}", manifest.display());
+    }
+
+    // Collect all dependencies from all crates
+    let mut all_deps = BTreeSet::new();
+    for manifest in &crate_manifests {
+        debcargo_info!("\nAnalyzing dependencies for {}...", manifest.display());
+
+        let (toolchain_deps, dependencies) = get_deb_dependencies(
+            &manifest.clone(),
+            &args.features.clone(),
+            args.all_features,
+            !args.no_default_features,
+            args.allow_prerelease_deps,
+            args.include_dev_dependencies,
+        )?;
+
+        let deps: BTreeSet<String> = toolchain_deps.into_iter().chain(dependencies).collect();
+        debcargo_info!("  Found {} dependencies", deps.len());
+        all_deps.extend(deps);
+    }
+
+    debcargo_info!(
+        "\nTotal unique dependencies across all crates: {}",
+        all_deps.len()
+    );
+
+    // Filter out local crate dependencies unless explicitly included
+    let mut deps_to_add = all_deps;
+    if !args.include_local_crates {
+        debcargo_info!("\nFiltering out local workspace crates...");
+        deps_to_add = filter_local_crate_dependencies(&deps_to_add, &crate_names);
+        debcargo_info!(
+            "Remaining dependencies after filtering: {}",
+            deps_to_add.len()
+        );
+    }
+
+    // Update debian/control with all dependencies
+    debcargo_info!("\nUpdating {}...", control_path);
+    update_build_dependencies(control_path, &deps_to_add, args.drop_unreferenced)?;
+
+    debcargo_info!("\nDone!");
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_is_local_package_exact_match() {
+        assert!(is_local_package("librust-foo-dev", "foo"));
+    }
+
+    #[test]
+    fn test_is_local_package_with_version() {
+        assert!(is_local_package("librust-foo-0.1-dev", "foo"));
+        assert!(is_local_package("librust-foo-0.1+default-dev", "foo"));
+        assert!(is_local_package(
+            "librust-desktop-edit-0.1+default-dev",
+            "desktop-edit"
+        ));
+    }
+
+    #[test]
+    fn test_is_local_package_with_feature() {
+        assert!(is_local_package("librust-foo+feature-dev", "foo"));
+        assert!(is_local_package("librust-foo+default-dev", "foo"));
+    }
+
+    #[test]
+    fn test_is_local_package_not_matching() {
+        assert!(!is_local_package("librust-bar-dev", "foo"));
+        assert!(!is_local_package("librust-foobar-dev", "foo"));
+        // Should not match if it's not a -dev package
+        assert!(!is_local_package("librust-foo", "foo"));
+        // Known limitation: librust-foo-0-dev WILL match "foo" as a versioned package.
+        // This is because we can't distinguish between a crate named "foo-0" and version
+        // "0" of crate "foo". This is a fundamental flaw with Debian's package naming.
+        assert!(is_local_package("librust-foo-0-dev", "foo"));
+    }
+
+    #[test]
+    fn test_is_local_package_hyphenated_names() {
+        assert!(is_local_package(
+            "librust-systemd-unit-edit-0.1+default-dev",
+            "systemd-unit-edit"
+        ));
+        assert!(is_local_package(
+            "librust-desktop-edit+feature-dev",
+            "desktop-edit"
+        ));
+    }
+
+    #[test]
+    fn test_filter_local_crate_dependencies_basic() {
+        let mut deps = BTreeSet::new();
+        deps.insert("librust-serde-dev".to_string());
+        deps.insert("librust-foo-dev".to_string());
+
+        let mut local_crates = HashSet::new();
+        local_crates.insert("foo".to_string());
+
+        let filtered = filter_local_crate_dependencies(&deps, &local_crates);
+
+        assert_eq!(filtered.len(), 1);
+        assert!(filtered.contains("librust-serde-dev"));
+        assert!(!filtered.contains("librust-foo-dev"));
+    }
+
+    #[test]
+    fn test_filter_local_crate_dependencies_with_version() {
+        let mut deps = BTreeSet::new();
+        deps.insert("librust-serde-dev".to_string());
+        deps.insert("librust-foo-0.1+default-dev".to_string());
+
+        let mut local_crates = HashSet::new();
+        local_crates.insert("foo".to_string());
+
+        let filtered = filter_local_crate_dependencies(&deps, &local_crates);
+
+        assert_eq!(filtered.len(), 1);
+        assert!(filtered.contains("librust-serde-dev"));
+        assert!(!filtered.contains("librust-foo-0.1+default-dev"));
+    }
+
+    #[test]
+    fn test_filter_local_crate_dependencies_hyphenated_crate_names() {
+        let mut deps = BTreeSet::new();
+        deps.insert("librust-serde-dev".to_string());
+        deps.insert("librust-desktop-edit-0.1+default-dev".to_string());
+        deps.insert("librust-systemd-unit-edit-0.1+default-dev".to_string());
+
+        let mut local_crates = HashSet::new();
+        local_crates.insert("desktop-edit".to_string());
+        local_crates.insert("systemd-unit-edit".to_string());
+
+        let filtered = filter_local_crate_dependencies(&deps, &local_crates);
+
+        assert_eq!(filtered.len(), 1);
+        assert!(filtered.contains("librust-serde-dev"));
+    }
+
+    #[test]
+    fn test_filter_local_crate_dependencies_with_features() {
+        let mut deps = BTreeSet::new();
+        deps.insert("librust-serde-dev".to_string());
+        deps.insert("librust-foo+feature-dev".to_string());
+        deps.insert("librust-foo+default-dev".to_string());
+
+        let mut local_crates = HashSet::new();
+        local_crates.insert("foo".to_string());
+
+        let filtered = filter_local_crate_dependencies(&deps, &local_crates);
+
+        assert_eq!(filtered.len(), 1);
+        assert!(filtered.contains("librust-serde-dev"));
+    }
+
+    #[test]
+    fn test_filter_local_crate_dependencies_with_version_constraints() {
+        let mut deps = BTreeSet::new();
+        deps.insert("librust-serde-dev".to_string());
+        deps.insert("librust-foo-0.1+default-dev (>= 0.1.3)".to_string());
+
+        let mut local_crates = HashSet::new();
+        local_crates.insert("foo".to_string());
+
+        let filtered = filter_local_crate_dependencies(&deps, &local_crates);
+
+        assert_eq!(filtered.len(), 1);
+        assert!(filtered.contains("librust-serde-dev"));
+    }
+
+    #[test]
+    fn test_filter_local_crate_dependencies_underscore_conversion() {
+        let mut deps = BTreeSet::new();
+        deps.insert("librust-serde-dev".to_string());
+        deps.insert("librust-my-crate-dev".to_string());
+
+        let mut local_crates = HashSet::new();
+        local_crates.insert("my_crate".to_string());
+
+        let filtered = filter_local_crate_dependencies(&deps, &local_crates);
+
+        assert_eq!(filtered.len(), 1);
+        assert!(filtered.contains("librust-serde-dev"));
+    }
+
+    #[test]
+    fn test_filter_local_crate_dependencies_empty() {
+        let deps = BTreeSet::new();
+        let local_crates = HashSet::new();
+
+        let filtered = filter_local_crate_dependencies(&deps, &local_crates);
+
+        assert_eq!(filtered.len(), 0);
+    }
+
+    #[test]
+    fn test_filter_local_crate_dependencies_no_local_crates() {
+        let mut deps = BTreeSet::new();
+        deps.insert("librust-serde-dev".to_string());
+        deps.insert("librust-foo-dev".to_string());
+
+        let local_crates = HashSet::new();
+
+        let filtered = filter_local_crate_dependencies(&deps, &local_crates);
+
+        assert_eq!(filtered.len(), 2);
+        assert!(filtered.contains("librust-serde-dev"));
+        assert!(filtered.contains("librust-foo-dev"));
+    }
+}
diff --git a/src/util.rs b/src/util.rs
new file mode 100644 (file)
index 0000000..2105cd7
--- /dev/null
@@ -0,0 +1,287 @@
+use std::borrow::Cow;
+use std::collections::{BTreeMap, BTreeSet, VecDeque};
+use std::ffi::OsStr;
+use std::fmt;
+use std::fs;
+use std::io::{BufRead, BufReader, Error};
+use std::iter::Iterator;
+#[cfg(unix)]
+use std::os::unix::ffi::OsStrExt;
+#[cfg(unix)]
+use std::os::unix::fs::symlink;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+
+use anyhow::bail;
+use itertools::Itertools;
+use walkdir::WalkDir;
+
+pub const HINT_SUFFIX: &str = ".debcargo.hint";
+
+#[cfg(unix)]
+pub fn hint_file_for(file: &Path) -> Option<Cow<'_, Path>> {
+    let file = file.as_os_str().as_bytes();
+    if file.len() >= HINT_SUFFIX.len()
+        && &file[file.len() - HINT_SUFFIX.len()..] == HINT_SUFFIX.as_bytes()
+    {
+        Some(Cow::Borrowed(Path::new(OsStr::from_bytes(
+            &file[..file.len() - HINT_SUFFIX.len()],
+        ))))
+    } else {
+        None
+    }
+}
+
+#[cfg(not(unix))]
+pub fn hint_file_for(file: &Path) -> Option<Cow<'_, Path>> {
+    if let Some(file_str) = file.to_str() {
+        if file_str.ends_with(HINT_SUFFIX) {
+            let trimmed_path = &file_str[..file_str.len() - HINT_SUFFIX.len()];
+            Some(Cow::Owned(PathBuf::from(trimmed_path)))
+        } else {
+            None
+        }
+    } else {
+        // Handle the case where the path is not representable as a string
+        None
+    }
+}
+
+pub fn lookup_fixmes(srcdir: &Path) -> Result<BTreeSet<PathBuf>, Error> {
+    let mut fixmes = BTreeSet::new();
+    let debiandir = srcdir.join("debian");
+    for entry in WalkDir::new(debiandir) {
+        let entry = entry?;
+        if entry.file_type().is_file() {
+            let file = fs::File::open(entry.path())?;
+            let reader = BufReader::new(file);
+            // If we find one FIXME we break the loop and check next file. Idea
+            // is only to find files with FIXME strings in it.
+            for line in reader.lines() {
+                match line {
+                    Ok(line_content) => {
+                        if line_content.contains("FIXME") {
+                            fixmes.insert(entry.path().to_path_buf());
+                            break;
+                        }
+                    }
+                    Err(e) => {
+                        debcargo_warn!(
+                            "Warning: Could not check for FIXMEs in file {:?}: {}",
+                            rel_p(entry.path(), srcdir),
+                            e
+                        );
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    // ignore hint files whose non-hint partners exists and don't have a FIXME
+    let fixmes = fixmes
+        .iter()
+        .filter(|f| match hint_file_for(f) {
+            Some(ff) => fixmes.contains(ff.as_ref()) || !ff.exists(),
+            None => true,
+        })
+        .cloned()
+        .collect::<BTreeSet<_>>();
+    Ok(fixmes)
+}
+
+pub fn rel_p<'a>(path: &'a Path, base: &'a Path) -> Cow<'a, str> {
+    path.strip_prefix(base).unwrap_or(path).to_string_lossy()
+}
+
+pub fn copy_tree(oldtree: &Path, newtree: &Path) -> Result<(), Error> {
+    for entry in WalkDir::new(oldtree) {
+        let entry = entry?;
+        if entry.depth() == 0 {
+            continue;
+        }
+        let oldpath = entry.path();
+        let newpath = newtree.join(oldpath.strip_prefix(oldtree).unwrap());
+        let ftype = entry.file_type();
+        match ftype {
+            f if f.is_dir() => {
+                fs::create_dir(newpath)?;
+            }
+            f if f.is_file() => {
+                fs::copy(oldpath, newpath)?;
+            }
+            #[cfg(unix)]
+            f if f.is_symlink() => {
+                symlink(fs::read_link(oldpath)?, newpath)?;
+            }
+            _ => {}
+        }
+    }
+    Ok(())
+}
+
+pub fn show_vec_with<'a, T, F>(it: impl IntoIterator<Item = &'a T>, f: F) -> String
+where
+    T: 'a,
+    F: FnMut(&T) -> String,
+{
+    Itertools::intersperse(it.into_iter().map(f), ", ".to_string()).collect::<String>()
+}
+
+pub fn show_vec<'a, T>(it: impl IntoIterator<Item = &'a T>) -> String
+where
+    T: fmt::Display + 'a,
+{
+    show_vec_with(it, ToString::to_string)
+}
+
+pub fn expect_success(cmd: &mut Command, err: &str) -> Result<(), anyhow::Error> {
+    match cmd.status() {
+        Ok(status) if status.success() => Ok(()),
+        Ok(_) => bail!("{err}"),
+        Err(e) => bail!("{err}\n{e}"),
+    }
+}
+
+pub(crate) fn traverse_depth<'a, V, F>(succ: &'a F, key: V) -> BTreeSet<V>
+where
+    V: Ord + Copy + 'a,
+    F: Fn(&V) -> Option<&'a Vec<V>>,
+{
+    let mut remain = VecDeque::from_iter([key]);
+    let mut seen = BTreeSet::new();
+    while let Some(v) = remain.pop_front() {
+        for v_ in succ(&v).into_iter().flatten() {
+            if !seen.contains(v_) {
+                seen.insert(*v_);
+                remain.push_back(*v_);
+            }
+        }
+    }
+    seen
+}
+
+/// Get a value that might be set at a key or any of its ancestor keys,
+/// whichever is closest. Error if there are conflicting definitions.
+#[allow(clippy::type_complexity)]
+pub(crate) fn get_transitive_val<
+    'a,
+    P: Fn(K) -> Option<&'a Vec<K>>,
+    F: Fn(K) -> Option<V>,
+    K: 'a + Ord + Copy,
+    V: Eq + Ord,
+>(
+    getparents: &'a P,
+    f: &F,
+    key: K,
+) -> Result<Option<V>, (K, Vec<(K, V)>)> {
+    let here = f(key);
+    if here.is_some() {
+        // value overrides anything from parents
+        Ok(here)
+    } else {
+        let mut candidates = Vec::new();
+        for par in getparents(key).into_iter().flatten() {
+            if let Some(v) = get_transitive_val(getparents, f, *par)? {
+                candidates.push((*par, v));
+            }
+        }
+        if candidates.is_empty() {
+            Ok(None) // here is None
+        } else {
+            let mut values = candidates.iter().map(|(_, v)| v).collect::<Vec<_>>();
+            values.sort();
+            values.dedup();
+            if values.len() == 1 {
+                Ok(candidates.pop().map(|(_, v)| v))
+            } else {
+                Err((key, candidates)) // handle conflict
+            }
+        }
+    }
+}
+
+pub fn graph_from_succ<V, FV, FL, E>(
+    seed: impl IntoIterator<Item = V>,
+    succ: &mut FV,
+    log: &mut FL,
+) -> Result<BTreeMap<V, BTreeSet<V>>, E>
+where
+    V: Ord + Clone,
+    FV: FnMut(&V) -> Result<(Vec<V>, Vec<V>), E>,
+    FL: FnMut(&VecDeque<V>, &BTreeMap<V, BTreeSet<V>>) -> Result<(), E>,
+{
+    let mut seen = BTreeSet::from_iter(seed);
+    let mut graph = BTreeMap::new();
+    let mut remain = VecDeque::from_iter(seen.iter().cloned());
+    while let Some(v) = remain.pop_front() {
+        log(&remain, &graph)?;
+        let (hard, soft) = succ(&v)?;
+        for v_ in hard.iter().chain(soft.iter()) {
+            if !seen.contains(v_) {
+                seen.insert(v_.clone());
+                remain.push_back(v_.clone());
+            }
+        }
+        graph.insert(v, BTreeSet::from_iter(hard));
+    }
+    Ok(graph)
+}
+
+pub fn succ_proj<S, T, F>(succ: &BTreeMap<S, BTreeSet<S>>, proj: F) -> BTreeMap<T, BTreeSet<T>>
+where
+    F: Fn(&S) -> T,
+    S: Ord,
+    T: Ord + Clone,
+{
+    let mut succ_proj: BTreeMap<T, BTreeSet<T>> = BTreeMap::new();
+    for (s, ss) in succ {
+        let e = succ_proj.entry(proj(s)).or_default();
+        for s_ in ss {
+            e.insert(proj(s_));
+        }
+    }
+    succ_proj
+}
+
+pub fn succ_to_pred<V>(succ: &BTreeMap<V, BTreeSet<V>>) -> BTreeMap<V, BTreeSet<V>>
+where
+    V: Ord + Clone,
+{
+    let mut pred: BTreeMap<V, BTreeSet<V>> = BTreeMap::new();
+    for (v, vv) in succ {
+        for v_ in vv {
+            pred.entry(v_.clone()).or_default().insert(v.clone());
+        }
+    }
+    pred
+}
+
+pub fn topo_sort<V>(
+    seed: impl IntoIterator<Item = V>,
+    succ: &BTreeMap<V, BTreeSet<V>>,
+    mut pred: BTreeMap<V, BTreeSet<V>>,
+) -> Result<Vec<V>, BTreeMap<V, BTreeSet<V>>>
+where
+    V: Ord + Clone,
+{
+    let empty = BTreeSet::new();
+    let mut remain = VecDeque::from_iter(seed);
+    let mut sort = Vec::new();
+    while let Some(v) = remain.pop_front() {
+        sort.push(v.clone());
+        for v_ in succ.get(&v).unwrap_or(&empty) {
+            let par = pred.entry(v_.clone()).or_default();
+            par.remove(&v);
+            if par.is_empty() {
+                remain.push_back(v_.clone());
+            }
+        }
+    }
+    pred.retain(|_, v| !v.is_empty());
+    if pred.is_empty() {
+        Ok(sort)
+    } else {
+        Err(pred)
+    }
+}
diff --git a/tests/clap_override.toml b/tests/clap_override.toml
new file mode 100644 (file)
index 0000000..8595e84
--- /dev/null
@@ -0,0 +1,17 @@
+uploaders = ["Sylvestre Ledru <sylvestre@debian.org>", "Ximin Luo <infinity0@debian.org>" ]
+
+[source]
+policy = "4.0.0"
+homepage = "https://clap.rs"
+
+[packages.lib]
+summary = "Simple, efficient and full featured Command line argument parser - source"
+description = """
+clap is used to parse and validate string of command line arguments provided by
+user at runtime. It provides help and version flags by default and additionally
+provide help subcommands in addition to traditional flags.
+This package provides clap with following default features.
+ * suggestions: provides did you mean suggestions on typos
+ * color: turns on colored error messages.
+ * wrap_help: Wrap the help at actual terminal width when available.
+"""
diff --git a/tests/config_tests.rs b/tests/config_tests.rs
new file mode 100644 (file)
index 0000000..81c966f
--- /dev/null
@@ -0,0 +1,158 @@
+extern crate debcargo;
+
+use debcargo::config::{Config, PackageKey};
+use std::path::Path;
+
+#[test]
+fn source_package_override() {
+    let filepath = Path::new("tests/clap_override.toml");
+
+    let config = Config::parse(filepath).unwrap();
+
+    assert!(config.source.is_some());
+    assert_eq!(config.packages.len(), 1);
+
+    assert_eq!(config.policy_version().unwrap(), "4.0.0");
+
+    assert_eq!(config.homepage().unwrap(), "https://clap.rs");
+
+    assert_eq!(config.section(), None);
+    assert_eq!(config.build_depends(), None);
+
+    let filepath = Path::new("tests/debcargo_override.toml");
+    let config = Config::parse(filepath).unwrap();
+
+    assert!(config.source.is_some());
+
+    assert_eq!(config.section().unwrap(), "rust");
+
+    assert_eq!(config.packages.len(), 2);
+    assert_eq!(
+        config.package_summary(PackageKey::Bin).unwrap(),
+        "Tool to create Debian package from Rust crate"
+    );
+
+    assert_eq!(
+        config.package_description(PackageKey::Bin).unwrap(),
+        "\
+This package provides debcargo a tool to create Debian source package from Rust
+crate. The package created by this tool is as per the packaging policy set by
+Debian Rust team.
+"
+    );
+
+    let extra = PackageKey::Extra("libblake3-0");
+    assert_eq!(config.package_architecture(extra).unwrap(), &vec!["any"]);
+    assert_eq!(config.package_section(extra).unwrap(), "libs");
+    assert_eq!(
+        config.package_depends(extra).unwrap(),
+        &vec!["${misc:Depends}", "${shlibs:Depends}"]
+    );
+    assert_eq!(
+        config.package_description(extra).unwrap(),
+        "BLAKE3 hash function - C library"
+    );
+}
+
+#[test]
+fn binary_package_override() {
+    let filepath = Path::new("tests/tiny-dfr_override.toml");
+    let config = Config::parse(filepath).unwrap();
+
+    assert_eq!(config.packages.len(), 1);
+
+    assert_eq!(
+        config.package_summary(PackageKey::Bin),
+        Some("dynamic touch bar daemon")
+    );
+
+    assert_eq!(
+        config.package_description(PackageKey::Bin),
+        Some(
+            "\
+    This package contains tiny-dfr, the userland touch bar daemon.
+
+tiny-dfr shows the function row and media control keys (brightness,
+volume, backlight, play, etc) on your touch bar. Currently supported
+platforms are Apple Silicon and T2 Macs.
+"
+        )
+    );
+
+    assert_eq!(
+        config.package_architecture(PackageKey::Bin),
+        Some(&vec!["arm64".to_string(), "amd64".to_string()])
+    );
+}
+
+#[test]
+fn sd_top_level() {
+    let filepath = Path::new("tests/debcargo_override_top_level.toml");
+    let config = Config::parse(filepath).unwrap();
+
+    assert!(config.source.is_some());
+
+    assert_eq!(config.section().unwrap(), "rust");
+
+    assert_eq!(
+        config.summary.unwrap(),
+        "Tool to create Debian package from Rust crate"
+    );
+    assert_eq!(
+        config.description.unwrap(),
+        "\
+This package provides debcargo a tool to create Debian source package from Rust
+crate. The package created by this tool is as per the packaging policy set by
+Debian Rust team.
+"
+    );
+}
+
+#[test]
+fn unknown_fields_captured_with_warning() {
+    let file_path = Path::new(env!("CARGO_TARGET_TMPDIR")).join("test_debcargo.toml");
+
+    // Test unknown field at top level
+    std::fs::write(
+        &file_path,
+        br#"
+semver_suffix = true
+overlay = "."
+verlay = "typo"  # This should be captured as an unknown field
+"#,
+    )
+    .unwrap();
+
+    let config = Config::parse(&file_path).unwrap();
+    assert!(config.unknown_fields.contains_key("verlay"));
+
+    // Test unknown field in source section
+    std::fs::write(
+        &file_path,
+        r#"
+[source]
+section = "rust"
+unknown_field = "value"
+"#,
+    )
+    .unwrap();
+
+    let config = Config::parse(&file_path).unwrap();
+    let source = config.source.unwrap();
+    assert!(source.unknown_fields.contains_key("unknown_field"));
+
+    // Test unknown field in packages section
+    std::fs::write(
+        &file_path,
+        r#"
+[packages.lib]
+section = "libs"
+unknwon_field = "value"
+"#,
+    )
+    .unwrap();
+
+    let config = Config::parse(&file_path).unwrap();
+    let lib_package = config.packages.get("lib").unwrap();
+    assert!(lib_package.unknown_fields.contains_key("unknwon_field"));
+}
diff --git a/tests/configs/aesni-0.10/debian/debcargo.toml b/tests/configs/aesni-0.10/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/aesni-0.10/debian/rules b/tests/configs/aesni-0.10/debian/rules
new file mode 100644 (file)
index 0000000..083418e
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate requires builder to set custom RUSTFLAGS
+# we can't do that in Debian due to architecture baselines
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/aesni/debian/debcargo.toml b/tests/configs/aesni/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/aesni/debian/rules b/tests/configs/aesni/debian/rules
new file mode 100644 (file)
index 0000000..083418e
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate requires builder to set custom RUSTFLAGS
+# we can't do that in Debian due to architecture baselines
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/afl-0.10/debian/debcargo.toml b/tests/configs/afl-0.10/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..c30d237
--- /dev/null
@@ -0,0 +1,8 @@
+semver_suffix = true
+overlay = "."
+
+[source]
+build_depends = ["llvm", "lld", "clang"]
+
+[packages.lib]
+depends = ["libclang-dev", "llvm", "lld", "clang"]
diff --git a/tests/configs/afl-0.10/debian/rules b/tests/configs/afl-0.10/debian/rules
new file mode 100644 (file)
index 0000000..5f52057
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+# needed by build script
+export XDG_DATA_HOME := $(CURDIR)/debian/xdg-data-home
+export CXXFLAGS := -Wno-unused-command-line-argument
+export CFLAGS := -Wno-unused-command-line-argument
+
+override_dh_strip_nondeterminism:
+       # dh_strip_nondeterminism can't parse these files
+       rm -rf $(CURDIR)/debian/libruzt-afl-*-dev/usr/share/cargo/registry/afl-*/AFLplusplus/docs/vuln_samples
+       dh_strip_nondeterminism
diff --git a/tests/configs/afl-0.13/debian/debcargo.toml b/tests/configs/afl-0.13/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/afl-0.13/debian/rules b/tests/configs/afl-0.13/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/aom-sys-0.3/debian/debcargo.toml b/tests/configs/aom-sys-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..3c5afd9
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["libaom-dev"]
diff --git a/tests/configs/ascii-0.8/debian/debcargo.toml b/tests/configs/ascii-0.8/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/ascii-0.8/debian/patches/fix-old-dep.patch b/tests/configs/ascii-0.8/debian/patches/fix-old-dep.patch
new file mode 100644 (file)
index 0000000..3aa27b5
--- /dev/null
@@ -0,0 +1,20 @@
+Crate authors like to put dev-dependencies in dependencies due to
+https://github.com/rust-lang/cargo/issues/1596
+
+Then due to lack of maintenance this pollutes the dependency set with old
+crates that no longer compile.
+
+Here, quickcheck 0.4 eventually depends on simd which no longer compiles.
+
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -22,9 +22,6 @@
+ [[test]]
+ name = "tests"
+ path = "tests.rs"
+-[dependencies.quickcheck]
+-version = "0.4.1"
+-optional = true
+ [features]
+ default = ["std"]
diff --git a/tests/configs/ascii-0.8/debian/patches/series b/tests/configs/ascii-0.8/debian/patches/series
new file mode 100644 (file)
index 0000000..f385166
--- /dev/null
@@ -0,0 +1 @@
+fix-old-dep.patch
diff --git a/tests/configs/aws-lc-fips-sys-0.12/debian/debcargo.toml b/tests/configs/aws-lc-fips-sys-0.12/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..16cd04f
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["golang"]
diff --git a/tests/configs/aws-lc-fips-sys-0.12/debian/rules b/tests/configs/aws-lc-fips-sys-0.12/debian/rules
new file mode 100644 (file)
index 0000000..7dd2db7
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# requires writable dir
+override_dh_auto_test:
+       dh_auto_test || true
+
diff --git a/tests/configs/blas-src-0.6/debian/debcargo.toml b/tests/configs/blas-src-0.6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/blas-src-0.6/debian/patches/drop-accelerate.diff b/tests/configs/blas-src-0.6/debian/patches/drop-accelerate.diff
new file mode 100644 (file)
index 0000000..a2ba0b1
--- /dev/null
@@ -0,0 +1,22 @@
+Index: blas-src-0.6.1/Cargo.toml
+===================================================================
+--- blas-src-0.6.1.orig/Cargo.toml
++++ blas-src-0.6.1/Cargo.toml
+@@ -22,9 +22,6 @@ keywords = ["linear-algebra"]
+ categories = ["science"]
+ license = "Apache-2.0/MIT"
+ repository = "https://github.com/blas-lapack-rs/blas-src"
+-[dependencies.accelerate-src]
+-version = "0.3"
+-optional = true
+ [dependencies.intel-mkl-src]
+ version = "0.5"
+@@ -39,7 +36,6 @@ version = "0.9"
+ optional = true
+ [features]
+-accelerate = ["accelerate-src"]
+ intel-mkl = ["intel-mkl-src"]
+ netlib = ["netlib-src"]
+ openblas = ["openblas-src"]
diff --git a/tests/configs/blas-src-0.6/debian/patches/series b/tests/configs/blas-src-0.6/debian/patches/series
new file mode 100644 (file)
index 0000000..c52a8c3
--- /dev/null
@@ -0,0 +1 @@
+drop-accelerate.diff
diff --git a/tests/configs/broken-dh-strip/debian/debcargo.toml b/tests/configs/broken-dh-strip/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/broken-dh-strip/debian/rules b/tests/configs/broken-dh-strip/debian/rules
new file mode 100755 (executable)
index 0000000..6c28854
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_strip:
diff --git a/tests/configs/broken-lto/debian/debcargo.toml b/tests/configs/broken-lto/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/broken-lto/debian/rules b/tests/configs/broken-lto/debian/rules
new file mode 100644 (file)
index 0000000..be9afde
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_dwz:
+       # Don't do anything. fails because of the
+       # https://github.com/rust-lang/rust/issues/66118
diff --git a/tests/configs/broken-upstream/debian/debcargo.toml b/tests/configs/broken-upstream/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/broken-upstream/debian/rules b/tests/configs/broken-upstream/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/brotli-decompressor-2/debian/debcargo.toml b/tests/configs/brotli-decompressor-2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/brotli-decompressor-2/debian/rules b/tests/configs/brotli-decompressor-2/debian/rules
new file mode 100644 (file)
index 0000000..be9afde
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_dwz:
+       # Don't do anything. fails because of the
+       # https://github.com/rust-lang/rust/issues/66118
diff --git a/tests/configs/clang-sys-0.23/debian/debcargo.toml b/tests/configs/clang-sys-0.23/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..583dcce
--- /dev/null
@@ -0,0 +1,8 @@
+semver_suffix = true
+overlay = "."
+
+[source]
+build_depends = ["llvm", "clang"]
+
+[packages.lib]
+depends = ["libclang-dev", "lld", "clang"]
diff --git a/tests/configs/clang-sys-0.26/debian/debcargo.toml b/tests/configs/clang-sys-0.26/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..583dcce
--- /dev/null
@@ -0,0 +1,8 @@
+semver_suffix = true
+overlay = "."
+
+[source]
+build_depends = ["llvm", "clang"]
+
+[packages.lib]
+depends = ["libclang-dev", "lld", "clang"]
diff --git a/tests/configs/clang-sys-1/debian/debcargo.toml b/tests/configs/clang-sys-1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..583dcce
--- /dev/null
@@ -0,0 +1,8 @@
+semver_suffix = true
+overlay = "."
+
+[source]
+build_depends = ["llvm", "clang"]
+
+[packages.lib]
+depends = ["libclang-dev", "lld", "clang"]
diff --git a/tests/configs/clang-sys/debian/debcargo.toml b/tests/configs/clang-sys/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..583dcce
--- /dev/null
@@ -0,0 +1,8 @@
+semver_suffix = true
+overlay = "."
+
+[source]
+build_depends = ["llvm", "clang"]
+
+[packages.lib]
+depends = ["libclang-dev", "lld", "clang"]
diff --git a/tests/configs/clippy-0.0/debian/debcargo.toml b/tests/configs/clippy-0.0/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/clippy-0.0/debian/rules b/tests/configs/clippy-0.0/debian/rules
new file mode 100644 (file)
index 0000000..b2056b4
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# clippy upstream now errors on purpose with the message "clippy is no longer
+# available on crates.io". Many old crates depend on clippy even though it is
+# a dev-dependency because of [3] and there are far too many to patch. So just
+# make the build of clippy "succeed"; it does not actually get used in the
+# build of a reverse-dependency anyway.
+#
+# [1] https://github.com/rust-lang/cargo/issues/1596
+
+override_dh_auto_test:
+       dh_auto_test || true
+
+override_dh_auto_install:
+       dh_auto_install || true
diff --git a/tests/configs/cmake-0.1/debian/debcargo.toml b/tests/configs/cmake-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..79ca598
--- /dev/null
@@ -0,0 +1,4 @@
+semver_suffix = true
+
+[packages.lib]
+depends = ["cmake"]
diff --git a/tests/configs/compiler-builtins-0.1/debian/debcargo.toml b/tests/configs/compiler-builtins-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/compiler-builtins-0.1/debian/rules b/tests/configs/compiler-builtins-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/compiler-error-0.1/debian/debcargo.toml b/tests/configs/compiler-error-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/compiler-error-0.1/debian/rules b/tests/configs/compiler-error-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/compiletest-rs-0.3/debian/debcargo.toml b/tests/configs/compiletest-rs-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/compiletest-rs-0.3/debian/rules b/tests/configs/compiletest-rs-0.3/debian/rules
new file mode 100644 (file)
index 0000000..8ad6a55
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate errors on the default feature by design
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/core-arch-0.1/debian/debcargo.toml b/tests/configs/core-arch-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/core-arch-0.1/debian/rules b/tests/configs/core-arch-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/core-error-0.0/debian/debcargo.toml b/tests/configs/core-error-0.0/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/core-error-0.0/debian/rules b/tests/configs/core-error-0.0/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/core-extensions-0.1/debian/debcargo.toml b/tests/configs/core-extensions-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/core-extensions-0.1/debian/rules b/tests/configs/core-extensions-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/core-foundation-0.9/debian/debcargo.toml b/tests/configs/core-foundation-0.9/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/core-foundation-0.9/debian/rules b/tests/configs/core-foundation-0.9/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/core-graphics-0.23/debian/debcargo.toml b/tests/configs/core-graphics-0.23/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/core-graphics-0.23/debian/rules b/tests/configs/core-graphics-0.23/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/core-graphics-types-0.1/debian/debcargo.toml b/tests/configs/core-graphics-types-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/core-graphics-types-0.1/debian/rules b/tests/configs/core-graphics-types-0.1/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/core-text-20/debian/debcargo.toml b/tests/configs/core-text-20/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/core-text-20/debian/rules b/tests/configs/core-text-20/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/cpp-demangle-0.3/debian/debcargo.toml b/tests/configs/cpp-demangle-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..7591b7f
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+bin = false
diff --git a/tests/configs/dav1d-sys-0.3/debian/debcargo.toml b/tests/configs/dav1d-sys-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..848a089
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["libdav1d-dev"]
diff --git a/tests/configs/dav1d-sys-0.3/debian/patches/relax-bindgen.patch b/tests/configs/dav1d-sys-0.3/debian/patches/relax-bindgen.patch
new file mode 100644 (file)
index 0000000..9874749
--- /dev/null
@@ -0,0 +1,13 @@
+Index: dav1d-sys-0.3.5/Cargo.toml
+===================================================================
+--- dav1d-sys-0.3.5.orig/Cargo.toml
++++ dav1d-sys-0.3.5/Cargo.toml
+@@ -24,7 +24,7 @@ dav1d = "0.9.0"
+ [dependencies]
+ [build-dependencies.bindgen]
+-version = "0.59.1"
++version = "0.66"
+ [build-dependencies.system-deps]
+ version = "6.0"
diff --git a/tests/configs/dav1d-sys-0.3/debian/patches/series b/tests/configs/dav1d-sys-0.3/debian/patches/series
new file mode 100644 (file)
index 0000000..49c3558
--- /dev/null
@@ -0,0 +1 @@
+relax-bindgen.patch
diff --git a/tests/configs/dav1d-sys-0.8/debian/debcargo.toml b/tests/configs/dav1d-sys-0.8/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..848a089
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["libdav1d-dev"]
diff --git a/tests/configs/derive-builder-0.9/debian/debcargo.toml b/tests/configs/derive-builder-0.9/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/derive-builder-0.9/debian/rules b/tests/configs/derive-builder-0.9/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/diesel-1/debian/debcargo.toml b/tests/configs/diesel-1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/diesel-1/debian/patches/fix-old-dep.patch b/tests/configs/diesel-1/debian/patches/fix-old-dep.patch
new file mode 100644 (file)
index 0000000..79a0a39
--- /dev/null
@@ -0,0 +1,21 @@
+Crate authors like to put dev-dependencies in dependencies due to
+https://github.com/rust-lang/cargo/issues/1596
+
+Then due to lack of maintenance this pollutes the dependency set with old
+crates that no longer compile.
+
+Here, quickcheck 0.4 eventually depends on simd which no longer compiles.
+
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -76,10 +76,6 @@
+ version = ">=0.3.0, <0.5.0"
+ optional = true
+-[dependencies.quickcheck]
+-version = "0.4"
+-optional = true
+-
+ [dependencies.r2d2]
+ version = ">= 0.8, < 0.9"
+ optional = true
diff --git a/tests/configs/diesel-1/debian/patches/series b/tests/configs/diesel-1/debian/patches/series
new file mode 100644 (file)
index 0000000..f385166
--- /dev/null
@@ -0,0 +1 @@
+fix-old-dep.patch
diff --git a/tests/configs/diesel-derives-2/debian/debcargo.toml b/tests/configs/diesel-derives-2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/diesel-derives-2/debian/rules b/tests/configs/diesel-derives-2/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/dwrote-0.11/debian/debcargo.toml b/tests/configs/dwrote-0.11/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/dwrote-0.11/debian/rules b/tests/configs/dwrote-0.11/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/exa-0.10/debian/debcargo.toml b/tests/configs/exa-0.10/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/exa-0.10/debian/rules b/tests/configs/exa-0.10/debian/rules
new file mode 100644 (file)
index 0000000..be9afde
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_dwz:
+       # Don't do anything. fails because of the
+       # https://github.com/rust-lang/rust/issues/66118
diff --git a/tests/configs/exa/debian/debcargo.toml b/tests/configs/exa/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/exa/debian/rules b/tests/configs/exa/debian/rules
new file mode 100644 (file)
index 0000000..be9afde
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_dwz:
+       # Don't do anything. fails because of the
+       # https://github.com/rust-lang/rust/issues/66118
diff --git a/tests/configs/fd-find-8/debian/debcargo.toml b/tests/configs/fd-find-8/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/fd-find-8/debian/rules b/tests/configs/fd-find-8/debian/rules
new file mode 100644 (file)
index 0000000..be9afde
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_dwz:
+       # Don't do anything. fails because of the
+       # https://github.com/rust-lang/rust/issues/66118
diff --git a/tests/configs/fsevent-0.4/debian/debcargo.toml b/tests/configs/fsevent-0.4/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/fsevent-0.4/debian/rules b/tests/configs/fsevent-0.4/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/fsevent-sys-2/debian/debcargo.toml b/tests/configs/fsevent-sys-2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/fsevent-sys-2/debian/rules b/tests/configs/fsevent-sys-2/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/heapsize-plugin-0.1/debian/debcargo.toml b/tests/configs/heapsize-plugin-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/heapsize-plugin-0.1/debian/rules b/tests/configs/heapsize-plugin-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/http-types-2/debian/debcargo.toml b/tests/configs/http-types-2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/http-types-2/debian/patches/fix-features.patch b/tests/configs/http-types-2/debian/patches/fix-features.patch
new file mode 100644 (file)
index 0000000..c357f23
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -83,7 +83,7 @@
+ version = "0.2.0"
+ [features]
+-async_std = ["fs"]
++async_std = ["async-std"] # replaces fs with deps of fs
+ cookie-secure = ["cookies", "cookie/secure"]
+ cookies = ["cookie"]
+ default = ["fs", "cookie-secure"]
diff --git a/tests/configs/http-types-2/debian/patches/series b/tests/configs/http-types-2/debian/patches/series
new file mode 100644 (file)
index 0000000..2447948
--- /dev/null
@@ -0,0 +1 @@
+fix-features.patch
diff --git a/tests/configs/hyperx-1/debian/debcargo.toml b/tests/configs/hyperx-1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/hyperx-1/debian/patches/relax-percent-encoding.patch b/tests/configs/hyperx-1/debian/patches/relax-percent-encoding.patch
new file mode 100644 (file)
index 0000000..1868251
--- /dev/null
@@ -0,0 +1,13 @@
+Index: hyperx-1.4.0/Cargo.toml
+===================================================================
+--- hyperx-1.4.0.orig/Cargo.toml
++++ hyperx-1.4.0/Cargo.toml
+@@ -43,7 +43,7 @@ version = ">=0.3.1, <0.4"
+ version = ">=0.3.2, <0.4"
+ [dependencies.percent-encoding]
+-version = ">=2.1.0, <2.2"
++version = "2.1.0"
+ [dependencies.unicase]
+ version = ">=2.6.0, <2.7"
diff --git a/tests/configs/hyperx-1/debian/patches/series b/tests/configs/hyperx-1/debian/patches/series
new file mode 100644 (file)
index 0000000..0490e99
--- /dev/null
@@ -0,0 +1 @@
+relax-percent-encoding.patch
diff --git a/tests/configs/hyperx/debian/debcargo.toml b/tests/configs/hyperx/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/hyperx/debian/patches/relax-percent-encoding.patch b/tests/configs/hyperx/debian/patches/relax-percent-encoding.patch
new file mode 100644 (file)
index 0000000..1868251
--- /dev/null
@@ -0,0 +1,13 @@
+Index: hyperx-1.4.0/Cargo.toml
+===================================================================
+--- hyperx-1.4.0.orig/Cargo.toml
++++ hyperx-1.4.0/Cargo.toml
+@@ -43,7 +43,7 @@ version = ">=0.3.1, <0.4"
+ version = ">=0.3.2, <0.4"
+ [dependencies.percent-encoding]
+-version = ">=2.1.0, <2.2"
++version = "2.1.0"
+ [dependencies.unicase]
+ version = ">=2.6.0, <2.7"
diff --git a/tests/configs/hyperx/debian/patches/series b/tests/configs/hyperx/debian/patches/series
new file mode 100644 (file)
index 0000000..0490e99
--- /dev/null
@@ -0,0 +1 @@
+relax-percent-encoding.patch
diff --git a/tests/configs/iana-time-zone-0.1/debian/debcargo.toml b/tests/configs/iana-time-zone-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/iana-time-zone-0.1/debian/patches/fix-windows-dep.patch b/tests/configs/iana-time-zone-0.1/debian/patches/fix-windows-dep.patch
new file mode 100644 (file)
index 0000000..4cca3bb
--- /dev/null
@@ -0,0 +1,10 @@
+Index: iana-time-zone-0.1.60/Cargo.toml
+===================================================================
+--- iana-time-zone-0.1.60.orig/Cargo.toml
++++ iana-time-zone-0.1.60/Cargo.toml
+@@ -54,4 +54,4 @@ version = "0.1.5"
+ version = "0.1.1"
+ [target."cfg(target_os = \"windows\")".dependencies.windows-core]
+-version = ">=0.50, <=0.52"
++version = "0.52"
diff --git a/tests/configs/iana-time-zone-0.1/debian/patches/series b/tests/configs/iana-time-zone-0.1/debian/patches/series
new file mode 100644 (file)
index 0000000..1934007
--- /dev/null
@@ -0,0 +1 @@
+fix-windows-dep.patch
diff --git a/tests/configs/jetscii-0.3/debian/debcargo.toml b/tests/configs/jetscii-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/jetscii-0.3/debian/rules b/tests/configs/jetscii-0.3/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/kqueue-1/debian/debcargo.toml b/tests/configs/kqueue-1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/kqueue-1/debian/rules b/tests/configs/kqueue-1/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/kqueue-sys-1/debian/debcargo.toml b/tests/configs/kqueue-sys-1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/kqueue-sys-1/debian/rules b/tests/configs/kqueue-sys-1/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/libdav1d-sys-0.6/debian/debcargo.toml b/tests/configs/libdav1d-sys-0.6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..1f2035a
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["libdav1d-dev", "meson", "nasm"]
diff --git a/tests/configs/libdbus-sys-0.2/debian/debcargo.toml b/tests/configs/libdbus-sys-0.2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..13f0492
--- /dev/null
@@ -0,0 +1,5 @@
+overlay = "."
+semver_suffix = true
+
+[packages.lib]
+depends = ["libdbus-1-dev"]
diff --git a/tests/configs/mysqlclient-src-0.1/debian/debcargo.toml b/tests/configs/mysqlclient-src-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..90c331e
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["libncurses-dev"]
diff --git a/tests/configs/mysqlclient-sys-0.2/debian/debcargo.toml b/tests/configs/mysqlclient-sys-0.2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..16cf81b
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["libmysqlclient-dev"]
diff --git a/tests/configs/mysqlclient-sys-0.4/debian/debcargo.toml b/tests/configs/mysqlclient-sys-0.4/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..16cf81b
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["libmysqlclient-dev"]
diff --git a/tests/configs/nasm-rs-0.2/debian/debcargo.toml b/tests/configs/nasm-rs-0.2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..2c3ba3d
--- /dev/null
@@ -0,0 +1,4 @@
+semver_suffix = true
+
+[packages.lib]
+depends = ["nasm"]
diff --git a/tests/configs/netlib-src-0.8/debian/debcargo.toml b/tests/configs/netlib-src-0.8/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..690060d
--- /dev/null
@@ -0,0 +1,5 @@
+overlay = "."
+semver_suffix = true
+
+[packages.lib]
+depends = ["gfortran"]
diff --git a/tests/configs/nodrop-union-0.1/debian/debcargo.toml b/tests/configs/nodrop-union-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/nodrop-union-0.1/debian/rules b/tests/configs/nodrop-union-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/nom-4/debian/debcargo.toml b/tests/configs/nom-4/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/nom-4/debian/rules b/tests/configs/nom-4/debian/rules
new file mode 100644 (file)
index 0000000..bbc019c
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate declares benches outside of crate path
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/old-version/debian/debcargo.toml b/tests/configs/old-version/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..544a9c6
--- /dev/null
@@ -0,0 +1,2 @@
+overlay = "."
+semver_suffix = true
diff --git a/tests/configs/once-cell-1/debian/debcargo.toml b/tests/configs/once-cell-1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/onig-6/debian/debcargo.toml b/tests/configs/onig-6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/onig-6/debian/rules b/tests/configs/onig-6/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/onig-sys-69/debian/debcargo.toml b/tests/configs/onig-sys-69/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/onig-sys-69/debian/rules b/tests/configs/onig-sys-69/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/only-macos/debian/debcargo.toml b/tests/configs/only-macos/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/only-macos/debian/rules b/tests/configs/only-macos/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/only-windows/debian/debcargo.toml b/tests/configs/only-windows/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/only-windows/debian/rules b/tests/configs/only-windows/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/openssl-sys-0.9/debian/debcargo.toml b/tests/configs/openssl-sys-0.9/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..c8a4273
--- /dev/null
@@ -0,0 +1,5 @@
+overlay = "."
+semver_suffix = true
+
+[packages.lib]
+depends = ["libssl-dev"]
diff --git a/tests/configs/openssl-sys-0.9/debian/patches/disable-bssl.patch b/tests/configs/openssl-sys-0.9/debian/patches/disable-bssl.patch
new file mode 100644 (file)
index 0000000..32e9b70
--- /dev/null
@@ -0,0 +1,14 @@
+Description: bssl-sys is a placeholder crate that doesn't actually compile as published on crates.io
+
+Index: openssl-sys-0.9.93/Cargo.toml
+===================================================================
+--- openssl-sys-0.9.93.orig/Cargo.toml
++++ openssl-sys-0.9.93/Cargo.toml
+@@ -34,4 +34,0 @@ repository = "https://github.com/sfackle
+-[dependencies.bssl-sys]
+-version = "0.1.0"
+-optional = true
+-
+@@ -61,1 +57,1 @@ version = "0.3.9"
+-unstable_boringssl = ["bssl-sys"]
++unstable_boringssl = []
diff --git a/tests/configs/openssl-sys-0.9/debian/patches/series b/tests/configs/openssl-sys-0.9/debian/patches/series
new file mode 100644 (file)
index 0000000..a8b638b
--- /dev/null
@@ -0,0 +1 @@
+disable-bssl.patch
diff --git a/tests/configs/packed-simd-0.3/debian/debcargo.toml b/tests/configs/packed-simd-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/packed-simd-0.3/debian/rules b/tests/configs/packed-simd-0.3/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/packed-simd-2-0.3/debian/debcargo.toml b/tests/configs/packed-simd-2-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/packed-simd-2-0.3/debian/rules b/tests/configs/packed-simd-2-0.3/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/petgraph-0.4/debian/debcargo.toml b/tests/configs/petgraph-0.4/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/petgraph-0.4/debian/patches/fix-old-dep.patch b/tests/configs/petgraph-0.4/debian/patches/fix-old-dep.patch
new file mode 100644 (file)
index 0000000..5ae18e6
--- /dev/null
@@ -0,0 +1,40 @@
+Crate authors like to put dev-dependencies in dependencies due to
+https://github.com/rust-lang/cargo/issues/1596
+
+Then due to lack of maintenance this pollutes the dependency set with old
+crates that no longer compile.
+
+Here, quickcheck 0.4 eventually depends on simd which no longer compiles.
+
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -21,7 +21,7 @@
+ license = "MIT/Apache-2.0"
+ repository = "https://github.com/bluss/petgraph"
+ [package.metadata.docs.rs]
+-features = ["serde-1", "quickcheck"]
++features = ["serde-1"]
+ [package.metadata.release]
+ no-dev-version = true
+@@ -40,11 +40,6 @@
+ version = "0.3.0"
+ optional = true
+-[dependencies.quickcheck]
+-version = "0.4"
+-optional = true
+-default-features = false
+-
+ [dependencies.serde]
+ version = "1.0"
+ optional = true
+@@ -66,7 +61,7 @@
+ version = "0.3"
+ [features]
+-all = ["unstable", "quickcheck", "stable_graph", "graphmap"]
++all = ["unstable", "stable_graph", "graphmap"]
+ default = ["graphmap", "stable_graph"]
+ generate = []
+ graphmap = ["ordermap"]
diff --git a/tests/configs/petgraph-0.4/debian/patches/series b/tests/configs/petgraph-0.4/debian/patches/series
new file mode 100644 (file)
index 0000000..f385166
--- /dev/null
@@ -0,0 +1 @@
+fix-old-dep.patch
diff --git a/tests/configs/phf-generator-0.10/debian/debcargo.toml b/tests/configs/phf-generator-0.10/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..7591b7f
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+bin = false
diff --git a/tests/configs/pkg-config-0.3/debian/debcargo.toml b/tests/configs/pkg-config-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..7a9da8f
--- /dev/null
@@ -0,0 +1,4 @@
+semver_suffix = true
+
+[packages.lib]
+depends = ["pkg-config"]
diff --git a/tests/configs/rav1e-0.6/debian/debcargo.toml b/tests/configs/rav1e-0.6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..c644066
--- /dev/null
@@ -0,0 +1,8 @@
+semver_suffix = true
+overlay = "."
+
+[source]
+build_depends = [
+    "cargo-c:native",
+]
+
diff --git a/tests/configs/rav1e-0.6/debian/patches/relax-clap.diff b/tests/configs/rav1e-0.6/debian/patches/relax-clap.diff
new file mode 100644 (file)
index 0000000..18d19a9
--- /dev/null
@@ -0,0 +1,13 @@
+Index: rav1e-0.6.6/Cargo.toml
+===================================================================
+--- rav1e-0.6.6.orig/Cargo.toml
++++ rav1e-0.6.6/Cargo.toml
+@@ -111,7 +111,7 @@ optional = true
+ version = "1.0"
+ [dependencies.clap]
+-version = "=4.0.32"
++version = "4.0.32"
+ features = [
+     "color",
+     "std",
diff --git a/tests/configs/rav1e-0.6/debian/patches/series b/tests/configs/rav1e-0.6/debian/patches/series
new file mode 100644 (file)
index 0000000..7c3dcab
--- /dev/null
@@ -0,0 +1 @@
+relax-clap.diff
diff --git a/tests/configs/redis-0.17/debian/debcargo.toml b/tests/configs/redis-0.17/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/redis-0.17/debian/rules b/tests/configs/redis-0.17/debian/rules
new file mode 100644 (file)
index 0000000..304a2b4
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate is buggy; fails to declare "alloc" feature on futures-util
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/redox-syscall-0.1/debian/debcargo.toml b/tests/configs/redox-syscall-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/redox-syscall-0.1/debian/rules b/tests/configs/redox-syscall-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/redox-users-0.3/debian/debcargo.toml b/tests/configs/redox-users-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/redox-users-0.3/debian/rules b/tests/configs/redox-users-0.3/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/rhai-1/debian/debcargo.toml b/tests/configs/rhai-1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/rhai-1/debian/rules b/tests/configs/rhai-1/debian/rules
new file mode 100644 (file)
index 0000000..be9afde
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_dwz:
+       # Don't do anything. fails because of the
+       # https://github.com/rust-lang/rust/issues/66118
diff --git a/tests/configs/ring-0.13/debian/debcargo.toml b/tests/configs/ring-0.13/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/ring-0.13/debian/rules b/tests/configs/ring-0.13/debian/rules
new file mode 100644 (file)
index 0000000..f5e1085
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate is super-over-zealous with lint settings
+# overrides our cargo wrapper's --cap-lints warn
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/ring-0.14/debian/debcargo.toml b/tests/configs/ring-0.14/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/ring-0.14/debian/rules b/tests/configs/ring-0.14/debian/rules
new file mode 100644 (file)
index 0000000..f5e1085
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate is super-over-zealous with lint settings
+# overrides our cargo wrapper's --cap-lints warn
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/rust-hawktracer-sys-0.4/debian/debcargo.toml b/tests/configs/rust-hawktracer-sys-0.4/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/rust-hawktracer-sys-0.4/debian/rules b/tests/configs/rust-hawktracer-sys-0.4/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/rust-lzma-0.5/debian/debcargo.toml b/tests/configs/rust-lzma-0.5/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..4b97b62
--- /dev/null
@@ -0,0 +1,5 @@
+overlay ="."
+semver_suffix = true
+
+[packages.lib]
+depends = ["liblzma-dev"]
diff --git a/tests/configs/salvo-extra-0.16/debian/debcargo.toml b/tests/configs/salvo-extra-0.16/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/salvo-extra-0.16/debian/rules b/tests/configs/salvo-extra-0.16/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/security-framework-2/debian/debcargo.toml b/tests/configs/security-framework-2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/security-framework-2/debian/rules b/tests/configs/security-framework-2/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/security-framework-sys-2/debian/debcargo.toml b/tests/configs/security-framework-sys-2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/security-framework-sys-2/debian/rules b/tests/configs/security-framework-sys-2/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/serde-qs-0.8/debian/debcargo.toml b/tests/configs/serde-qs-0.8/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/serde-qs-0.8/debian/patches/fix-actix-web-dep.patch b/tests/configs/serde-qs-0.8/debian/patches/fix-actix-web-dep.patch
new file mode 100644 (file)
index 0000000..d44aff6
--- /dev/null
@@ -0,0 +1,30 @@
+actix-web eventually depends on actix-connect 1.0.2
+actix-connect 1.0.2 depends on prerelease trust-dns-resolver 0.18.0-alpha.2,
+which declares broken deps on trust-dns-proto "0.18.0" - should be "=0.18.0-alpha.2"
+
+debcargo doesn't support prerelease versions because semver compatibility
+doesn't apply. So patching trust-dns-resolver to fix their bug is not an
+option for us here. So just disable actix-web 2 here.
+
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -30,12 +30,6 @@
+ default-features = false
+ package = "actix-web"
+-[dependencies.actix-web2]
+-version = "2.0"
+-optional = true
+-default-features = false
+-package = "actix-web"
+-
+ [dependencies.futures]
+ version = "0.3"
+ optional = true
+@@ -75,6 +69,5 @@
+ [features]
+ actix = ["actix-web", "futures"]
+-actix2 = ["actix-web2", "futures"]
+ default = []
+ warp = ["futures", "tracing", "warp-framework"]
diff --git a/tests/configs/serde-qs-0.8/debian/patches/series b/tests/configs/serde-qs-0.8/debian/patches/series
new file mode 100644 (file)
index 0000000..03ed99c
--- /dev/null
@@ -0,0 +1 @@
+fix-actix-web-dep.patch
diff --git a/tests/configs/servo-fontconfig-sys-5/debian/debcargo.toml b/tests/configs/servo-fontconfig-sys-5/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..83cc783
--- /dev/null
@@ -0,0 +1,4 @@
+semver_suffix = true
+
+[packages.lib]
+depends = ["libfontconfig-dev"]
diff --git a/tests/configs/sleef-sys-0.1/debian/debcargo.toml b/tests/configs/sleef-sys-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/sleef-sys-0.1/debian/rules b/tests/configs/sleef-sys-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/spin-0.4/debian/debcargo.toml b/tests/configs/spin-0.4/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/spin-0.4/debian/rules b/tests/configs/spin-0.4/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/structopt-0.3/debian/debcargo.toml b/tests/configs/structopt-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/structopt-0.3/debian/patches/disable-lint-feature.diff b/tests/configs/structopt-0.3/debian/patches/disable-lint-feature.diff
new file mode 100644 (file)
index 0000000..5bdae4f
--- /dev/null
@@ -0,0 +1,13 @@
+Index: structopt/Cargo.toml
+===================================================================
+--- structopt.orig/Cargo.toml
++++ structopt/Cargo.toml
+@@ -51,7 +51,7 @@ color = ["clap/color"]
+ debug = ["clap/debug"]
+ default = ["clap/default"]
+ doc = ["clap/doc"]
+-lints = ["clap/lints"]
++#lints = ["clap/lints"]
+ no_cargo = ["clap/no_cargo"]
+ #paw = ["structopt-derive/paw", "paw_dep"]
+ suggestions = ["clap/suggestions"]
diff --git a/tests/configs/structopt-0.3/debian/patches/disable-paw.diff b/tests/configs/structopt-0.3/debian/patches/disable-paw.diff
new file mode 100644 (file)
index 0000000..c1ba307
--- /dev/null
@@ -0,0 +1,28 @@
+Index: structopt/Cargo.toml
+===================================================================
+--- structopt.orig/Cargo.toml
++++ structopt/Cargo.toml
+@@ -28,10 +28,10 @@
+ [dependencies.lazy_static]
+ version = "1.4.0"
+-[dependencies.paw_dep]
+-version = "1"
+-optional = true
+-package = "paw"
++#[dependencies.paw_dep]
++#version = "1"
++#optional = true
++#package = "paw"
+ [dependencies.structopt-derive]
+ version = "=0.4.18"
+@@ -53,7 +53,7 @@
+ doc = ["clap/doc"]
+ lints = ["clap/lints"]
+ no_cargo = ["clap/no_cargo"]
+-paw = ["structopt-derive/paw", "paw_dep"]
++#paw = ["structopt-derive/paw", "paw_dep"]
+ suggestions = ["clap/suggestions"]
+ wrap_help = ["clap/wrap_help"]
+ yaml = ["clap/yaml"]
diff --git a/tests/configs/structopt-0.3/debian/patches/series b/tests/configs/structopt-0.3/debian/patches/series
new file mode 100644 (file)
index 0000000..d5e4f35
--- /dev/null
@@ -0,0 +1,2 @@
+disable-paw.diff
+disable-lint-feature.diff
diff --git a/tests/configs/system-configuration-0.5/debian/debcargo.toml b/tests/configs/system-configuration-0.5/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/system-configuration-0.5/debian/rules b/tests/configs/system-configuration-0.5/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/system-configuration-0.6/debian/debcargo.toml b/tests/configs/system-configuration-0.6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/system-configuration-0.6/debian/rules b/tests/configs/system-configuration-0.6/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/system-configuration-sys-0.5/debian/debcargo.toml b/tests/configs/system-configuration-sys-0.5/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/system-configuration-sys-0.5/debian/rules b/tests/configs/system-configuration-sys-0.5/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/system-configuration-sys-0.6/debian/debcargo.toml b/tests/configs/system-configuration-sys-0.6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/system-configuration-sys-0.6/debian/rules b/tests/configs/system-configuration-sys-0.6/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/system-deps-6/debian/debcargo.toml b/tests/configs/system-deps-6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/system-deps-6/debian/rules b/tests/configs/system-deps-6/debian/rules
new file mode 100755 (executable)
index 0000000..6c28854
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_strip:
diff --git a/tests/configs/tiny-keccak-2/debian/debcargo.toml b/tests/configs/tiny-keccak-2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/tiny-keccak-2/debian/rules b/tests/configs/tiny-keccak-2/debian/rules
new file mode 100644 (file)
index 0000000..bf5ebf1
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate errors on purpose when no features are enabled
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/vcpkg-0.2/debian/debcargo.toml b/tests/configs/vcpkg-0.2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..0c74ebf
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+excludes = ["test-data/**"]
diff --git a/tests/configs/wepoll-ffi-0.1/debian/debcargo.toml b/tests/configs/wepoll-ffi-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/wepoll-ffi-0.1/debian/rules b/tests/configs/wepoll-ffi-0.1/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/windows-0.32/debian/debcargo.toml b/tests/configs/windows-0.32/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/windows-0.32/debian/rules b/tests/configs/windows-0.32/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/windows-0.48/debian/debcargo.toml b/tests/configs/windows-0.48/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/windows-0.48/debian/rules b/tests/configs/windows-0.48/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/windows-0.54/debian/changelog b/tests/configs/windows-0.54/debian/changelog
new file mode 100644 (file)
index 0000000..44e099c
--- /dev/null
@@ -0,0 +1,6 @@
+rust-windows-0.54 (0.54.0-1) UNRELEASED-FIXME-AUTOGENERATED-DEBCARGO; urgency=medium
+
+  * Team upload.
+  * Package windows 0.54.0 from crates.io using debcargo 2.6.1
+
+ -- Fabian Grünbichler <debian@fabian.gruenbichler.email>  Sat, 6 Jul 2024 21:13:52 +0200
diff --git a/tests/configs/windows-0.54/debian/debcargo.toml b/tests/configs/windows-0.54/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..96a9bd9
--- /dev/null
@@ -0,0 +1,7 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+test_is_broken = false
+[packages."lib+Win32_Foundation"]
+test_is_broken = false
diff --git a/tests/configs/windows-0.54/debian/patches/remove-cycles.patch b/tests/configs/windows-0.54/debian/patches/remove-cycles.patch
new file mode 100644 (file)
index 0000000..1719bff
--- /dev/null
@@ -0,0 +1,1382 @@
+Index: rust-windows-0.54-0.54.0/Cargo.toml
+===================================================================
+--- rust-windows-0.54-0.54.0.orig/Cargo.toml
++++ rust-windows-0.54-0.54.0/Cargo.toml
+@@ -46,692 +46,692 @@ optional = true
+ version = "0.52.3"
+ [features]
+-AI = ["Foundation"]
+-AI_MachineLearning = ["AI"]
+-ApplicationModel = ["Foundation"]
+-ApplicationModel_Activation = ["ApplicationModel"]
+-ApplicationModel_AppExtensions = ["ApplicationModel"]
+-ApplicationModel_AppService = ["ApplicationModel"]
+-ApplicationModel_Appointments = ["ApplicationModel"]
+-ApplicationModel_Appointments_AppointmentsProvider = ["ApplicationModel_Appointments"]
+-ApplicationModel_Appointments_DataProvider = ["ApplicationModel_Appointments"]
+-ApplicationModel_Background = ["ApplicationModel"]
+-ApplicationModel_Calls = ["ApplicationModel"]
+-ApplicationModel_Calls_Background = ["ApplicationModel_Calls"]
+-ApplicationModel_Calls_Provider = ["ApplicationModel_Calls"]
+-ApplicationModel_Chat = ["ApplicationModel"]
+-ApplicationModel_CommunicationBlocking = ["ApplicationModel"]
+-ApplicationModel_Contacts = ["ApplicationModel"]
+-ApplicationModel_Contacts_DataProvider = ["ApplicationModel_Contacts"]
+-ApplicationModel_Contacts_Provider = ["ApplicationModel_Contacts"]
+-ApplicationModel_ConversationalAgent = ["ApplicationModel"]
+-ApplicationModel_Core = ["ApplicationModel"]
+-ApplicationModel_DataTransfer = ["ApplicationModel"]
+-ApplicationModel_DataTransfer_DragDrop = ["ApplicationModel_DataTransfer"]
+-ApplicationModel_DataTransfer_DragDrop_Core = ["ApplicationModel_DataTransfer_DragDrop"]
+-ApplicationModel_DataTransfer_ShareTarget = ["ApplicationModel_DataTransfer"]
+-ApplicationModel_Email = ["ApplicationModel"]
+-ApplicationModel_Email_DataProvider = ["ApplicationModel_Email"]
+-ApplicationModel_ExtendedExecution = ["ApplicationModel"]
+-ApplicationModel_ExtendedExecution_Foreground = ["ApplicationModel_ExtendedExecution"]
+-ApplicationModel_Holographic = ["ApplicationModel"]
+-ApplicationModel_LockScreen = ["ApplicationModel"]
+-ApplicationModel_Payments = ["ApplicationModel"]
+-ApplicationModel_Payments_Provider = ["ApplicationModel_Payments"]
+-ApplicationModel_Preview = ["ApplicationModel"]
+-ApplicationModel_Preview_Holographic = ["ApplicationModel_Preview"]
+-ApplicationModel_Preview_InkWorkspace = ["ApplicationModel_Preview"]
+-ApplicationModel_Preview_Notes = ["ApplicationModel_Preview"]
+-ApplicationModel_Resources = ["ApplicationModel"]
+-ApplicationModel_Resources_Core = ["ApplicationModel_Resources"]
+-ApplicationModel_Resources_Management = ["ApplicationModel_Resources"]
+-ApplicationModel_Search = ["ApplicationModel"]
+-ApplicationModel_Search_Core = ["ApplicationModel_Search"]
+-ApplicationModel_Store = ["ApplicationModel"]
+-ApplicationModel_Store_LicenseManagement = ["ApplicationModel_Store"]
+-ApplicationModel_Store_Preview = ["ApplicationModel_Store"]
+-ApplicationModel_Store_Preview_InstallControl = ["ApplicationModel_Store_Preview"]
+-ApplicationModel_UserActivities = ["ApplicationModel"]
+-ApplicationModel_UserActivities_Core = ["ApplicationModel_UserActivities"]
+-ApplicationModel_UserDataAccounts = ["ApplicationModel"]
+-ApplicationModel_UserDataAccounts_Provider = ["ApplicationModel_UserDataAccounts"]
+-ApplicationModel_UserDataAccounts_SystemAccess = ["ApplicationModel_UserDataAccounts"]
+-ApplicationModel_UserDataTasks = ["ApplicationModel"]
+-ApplicationModel_UserDataTasks_DataProvider = ["ApplicationModel_UserDataTasks"]
+-ApplicationModel_VoiceCommands = ["ApplicationModel"]
+-ApplicationModel_Wallet = ["ApplicationModel"]
+-ApplicationModel_Wallet_System = ["ApplicationModel_Wallet"]
+-Data = ["Foundation"]
+-Data_Html = ["Data"]
+-Data_Json = ["Data"]
+-Data_Pdf = ["Data"]
+-Data_Text = ["Data"]
+-Data_Xml = ["Data"]
+-Data_Xml_Dom = ["Data_Xml"]
+-Data_Xml_Xsl = ["Data_Xml"]
+-Devices = ["Foundation"]
+-Devices_Adc = ["Devices"]
+-Devices_Adc_Provider = ["Devices_Adc"]
+-Devices_Background = ["Devices"]
+-Devices_Bluetooth = ["Devices"]
+-Devices_Bluetooth_Advertisement = ["Devices_Bluetooth"]
+-Devices_Bluetooth_Background = ["Devices_Bluetooth"]
+-Devices_Bluetooth_GenericAttributeProfile = ["Devices_Bluetooth"]
+-Devices_Bluetooth_Rfcomm = ["Devices_Bluetooth"]
+-Devices_Custom = ["Devices"]
+-Devices_Display = ["Devices"]
+-Devices_Display_Core = ["Devices_Display"]
+-Devices_Enumeration = ["Devices"]
+-Devices_Enumeration_Pnp = ["Devices_Enumeration"]
+-Devices_Geolocation = ["Devices"]
+-Devices_Geolocation_Geofencing = ["Devices_Geolocation"]
+-Devices_Geolocation_Provider = ["Devices_Geolocation"]
+-Devices_Gpio = ["Devices"]
+-Devices_Gpio_Provider = ["Devices_Gpio"]
+-Devices_Haptics = ["Devices"]
+-Devices_HumanInterfaceDevice = ["Devices"]
+-Devices_I2c = ["Devices"]
+-Devices_I2c_Provider = ["Devices_I2c"]
+-Devices_Input = ["Devices"]
+-Devices_Input_Preview = ["Devices_Input"]
+-Devices_Lights = ["Devices"]
+-Devices_Lights_Effects = ["Devices_Lights"]
+-Devices_Midi = ["Devices"]
+-Devices_PointOfService = ["Devices"]
+-Devices_PointOfService_Provider = ["Devices_PointOfService"]
+-Devices_Portable = ["Devices"]
+-Devices_Power = ["Devices"]
+-Devices_Printers = ["Devices"]
+-Devices_Printers_Extensions = ["Devices_Printers"]
+-Devices_Pwm = ["Devices"]
+-Devices_Pwm_Provider = ["Devices_Pwm"]
+-Devices_Radios = ["Devices"]
+-Devices_Scanners = ["Devices"]
+-Devices_Sensors = ["Devices"]
+-Devices_Sensors_Custom = ["Devices_Sensors"]
+-Devices_SerialCommunication = ["Devices"]
+-Devices_SmartCards = ["Devices"]
+-Devices_Sms = ["Devices"]
+-Devices_Spi = ["Devices"]
+-Devices_Spi_Provider = ["Devices_Spi"]
+-Devices_Usb = ["Devices"]
+-Devices_WiFi = ["Devices"]
+-Devices_WiFiDirect = ["Devices"]
+-Devices_WiFiDirect_Services = ["Devices_WiFiDirect"]
+-Embedded = ["Foundation"]
+-Embedded_DeviceLockdown = ["Embedded"]
++AI = []
++AI_MachineLearning = []
++ApplicationModel = []
++ApplicationModel_Activation = []
++ApplicationModel_AppExtensions = []
++ApplicationModel_AppService = []
++ApplicationModel_Appointments = []
++ApplicationModel_Appointments_AppointmentsProvider = []
++ApplicationModel_Appointments_DataProvider = []
++ApplicationModel_Background = []
++ApplicationModel_Calls = []
++ApplicationModel_Calls_Background = []
++ApplicationModel_Calls_Provider = []
++ApplicationModel_Chat = []
++ApplicationModel_CommunicationBlocking = []
++ApplicationModel_Contacts = []
++ApplicationModel_Contacts_DataProvider = []
++ApplicationModel_Contacts_Provider = []
++ApplicationModel_ConversationalAgent = []
++ApplicationModel_Core = []
++ApplicationModel_DataTransfer = []
++ApplicationModel_DataTransfer_DragDrop = []
++ApplicationModel_DataTransfer_DragDrop_Core = []
++ApplicationModel_DataTransfer_ShareTarget = []
++ApplicationModel_Email = []
++ApplicationModel_Email_DataProvider = []
++ApplicationModel_ExtendedExecution = []
++ApplicationModel_ExtendedExecution_Foreground = []
++ApplicationModel_Holographic = []
++ApplicationModel_LockScreen = []
++ApplicationModel_Payments = []
++ApplicationModel_Payments_Provider = []
++ApplicationModel_Preview = []
++ApplicationModel_Preview_Holographic = []
++ApplicationModel_Preview_InkWorkspace = []
++ApplicationModel_Preview_Notes = []
++ApplicationModel_Resources = []
++ApplicationModel_Resources_Core = []
++ApplicationModel_Resources_Management = []
++ApplicationModel_Search = []
++ApplicationModel_Search_Core = []
++ApplicationModel_Store = []
++ApplicationModel_Store_LicenseManagement = []
++ApplicationModel_Store_Preview = []
++ApplicationModel_Store_Preview_InstallControl = []
++ApplicationModel_UserActivities = []
++ApplicationModel_UserActivities_Core = []
++ApplicationModel_UserDataAccounts = []
++ApplicationModel_UserDataAccounts_Provider = []
++ApplicationModel_UserDataAccounts_SystemAccess = []
++ApplicationModel_UserDataTasks = []
++ApplicationModel_UserDataTasks_DataProvider = []
++ApplicationModel_VoiceCommands = []
++ApplicationModel_Wallet = []
++ApplicationModel_Wallet_System = []
++Data = []
++Data_Html = []
++Data_Json = []
++Data_Pdf = []
++Data_Text = []
++Data_Xml = []
++Data_Xml_Dom = []
++Data_Xml_Xsl = []
++Devices = []
++Devices_Adc = []
++Devices_Adc_Provider = []
++Devices_Background = []
++Devices_Bluetooth = []
++Devices_Bluetooth_Advertisement = []
++Devices_Bluetooth_Background = []
++Devices_Bluetooth_GenericAttributeProfile = []
++Devices_Bluetooth_Rfcomm = []
++Devices_Custom = []
++Devices_Display = []
++Devices_Display_Core = []
++Devices_Enumeration = []
++Devices_Enumeration_Pnp = []
++Devices_Geolocation = []
++Devices_Geolocation_Geofencing = []
++Devices_Geolocation_Provider = []
++Devices_Gpio = []
++Devices_Gpio_Provider = []
++Devices_Haptics = []
++Devices_HumanInterfaceDevice = []
++Devices_I2c = []
++Devices_I2c_Provider = []
++Devices_Input = []
++Devices_Input_Preview = []
++Devices_Lights = []
++Devices_Lights_Effects = []
++Devices_Midi = []
++Devices_PointOfService = []
++Devices_PointOfService_Provider = []
++Devices_Portable = []
++Devices_Power = []
++Devices_Printers = []
++Devices_Printers_Extensions = []
++Devices_Pwm = []
++Devices_Pwm_Provider = []
++Devices_Radios = []
++Devices_Scanners = []
++Devices_Sensors = []
++Devices_Sensors_Custom = []
++Devices_SerialCommunication = []
++Devices_SmartCards = []
++Devices_Sms = []
++Devices_Spi = []
++Devices_Spi_Provider = []
++Devices_Usb = []
++Devices_WiFi = []
++Devices_WiFiDirect = []
++Devices_WiFiDirect_Services = []
++Embedded = []
++Embedded_DeviceLockdown = []
+ Foundation = []
+-Foundation_Collections = ["Foundation"]
+-Foundation_Diagnostics = ["Foundation"]
+-Foundation_Metadata = ["Foundation"]
+-Foundation_Numerics = ["Foundation"]
+-Gaming = ["Foundation"]
+-Gaming_Input = ["Gaming"]
+-Gaming_Input_Custom = ["Gaming_Input"]
+-Gaming_Input_ForceFeedback = ["Gaming_Input"]
+-Gaming_Input_Preview = ["Gaming_Input"]
+-Gaming_Preview = ["Gaming"]
+-Gaming_Preview_GamesEnumeration = ["Gaming_Preview"]
+-Gaming_UI = ["Gaming"]
+-Gaming_XboxLive = ["Gaming"]
+-Gaming_XboxLive_Storage = ["Gaming_XboxLive"]
+-Globalization = ["Foundation"]
+-Globalization_Collation = ["Globalization"]
+-Globalization_DateTimeFormatting = ["Globalization"]
+-Globalization_Fonts = ["Globalization"]
+-Globalization_NumberFormatting = ["Globalization"]
+-Globalization_PhoneNumberFormatting = ["Globalization"]
+-Graphics = ["Foundation"]
+-Graphics_Capture = ["Graphics"]
+-Graphics_DirectX = ["Graphics"]
+-Graphics_DirectX_Direct3D11 = ["Graphics_DirectX"]
+-Graphics_Display = ["Graphics"]
+-Graphics_Display_Core = ["Graphics_Display"]
+-Graphics_Effects = ["Graphics"]
+-Graphics_Holographic = ["Graphics"]
+-Graphics_Imaging = ["Graphics"]
+-Graphics_Printing = ["Graphics"]
+-Graphics_Printing3D = ["Graphics"]
+-Graphics_Printing_OptionDetails = ["Graphics_Printing"]
+-Graphics_Printing_PrintSupport = ["Graphics_Printing"]
+-Graphics_Printing_PrintTicket = ["Graphics_Printing"]
+-Graphics_Printing_Workflow = ["Graphics_Printing"]
+-Management = ["Foundation"]
+-Management_Core = ["Management"]
+-Management_Deployment = ["Management"]
+-Management_Deployment_Preview = ["Management_Deployment"]
+-Management_Policies = ["Management"]
+-Management_Update = ["Management"]
+-Management_Workplace = ["Management"]
+-Media = ["Foundation"]
+-Media_AppBroadcasting = ["Media"]
+-Media_AppRecording = ["Media"]
+-Media_Audio = ["Media"]
+-Media_Capture = ["Media"]
+-Media_Capture_Core = ["Media_Capture"]
+-Media_Capture_Frames = ["Media_Capture"]
+-Media_Casting = ["Media"]
+-Media_ClosedCaptioning = ["Media"]
+-Media_ContentRestrictions = ["Media"]
+-Media_Control = ["Media"]
+-Media_Core = ["Media"]
+-Media_Core_Preview = ["Media_Core"]
+-Media_Devices = ["Media"]
+-Media_Devices_Core = ["Media_Devices"]
+-Media_DialProtocol = ["Media"]
+-Media_Editing = ["Media"]
+-Media_Effects = ["Media"]
+-Media_FaceAnalysis = ["Media"]
+-Media_Import = ["Media"]
+-Media_MediaProperties = ["Media"]
+-Media_Miracast = ["Media"]
+-Media_Ocr = ["Media"]
+-Media_PlayTo = ["Media"]
+-Media_Playback = ["Media"]
+-Media_Playlists = ["Media"]
+-Media_Protection = ["Media"]
+-Media_Protection_PlayReady = ["Media_Protection"]
+-Media_Render = ["Media"]
+-Media_SpeechRecognition = ["Media"]
+-Media_SpeechSynthesis = ["Media"]
+-Media_Streaming = ["Media"]
+-Media_Streaming_Adaptive = ["Media_Streaming"]
+-Media_Transcoding = ["Media"]
+-Networking = ["Foundation"]
+-Networking_BackgroundTransfer = ["Networking"]
+-Networking_Connectivity = ["Networking"]
+-Networking_NetworkOperators = ["Networking"]
+-Networking_Proximity = ["Networking"]
+-Networking_PushNotifications = ["Networking"]
+-Networking_ServiceDiscovery = ["Networking"]
+-Networking_ServiceDiscovery_Dnssd = ["Networking_ServiceDiscovery"]
+-Networking_Sockets = ["Networking"]
+-Networking_Vpn = ["Networking"]
+-Networking_XboxLive = ["Networking"]
+-Perception = ["Foundation"]
+-Perception_Automation = ["Perception"]
+-Perception_Automation_Core = ["Perception_Automation"]
+-Perception_People = ["Perception"]
+-Perception_Spatial = ["Perception"]
+-Perception_Spatial_Preview = ["Perception_Spatial"]
+-Perception_Spatial_Surfaces = ["Perception_Spatial"]
+-Phone = ["Foundation"]
+-Phone_ApplicationModel = ["Phone"]
+-Phone_Devices = ["Phone"]
+-Phone_Devices_Notification = ["Phone_Devices"]
+-Phone_Devices_Power = ["Phone_Devices"]
+-Phone_Management = ["Phone"]
+-Phone_Management_Deployment = ["Phone_Management"]
+-Phone_Media = ["Phone"]
+-Phone_Media_Devices = ["Phone_Media"]
+-Phone_Notification = ["Phone"]
+-Phone_Notification_Management = ["Phone_Notification"]
+-Phone_PersonalInformation = ["Phone"]
+-Phone_PersonalInformation_Provisioning = ["Phone_PersonalInformation"]
+-Phone_Speech = ["Phone"]
+-Phone_Speech_Recognition = ["Phone_Speech"]
+-Phone_StartScreen = ["Phone"]
+-Phone_System = ["Phone"]
+-Phone_System_Power = ["Phone_System"]
+-Phone_System_Profile = ["Phone_System"]
+-Phone_System_UserProfile = ["Phone_System"]
+-Phone_System_UserProfile_GameServices = ["Phone_System_UserProfile"]
+-Phone_System_UserProfile_GameServices_Core = ["Phone_System_UserProfile_GameServices"]
+-Phone_UI = ["Phone"]
+-Phone_UI_Input = ["Phone_UI"]
+-Security = ["Foundation"]
+-Security_Authentication = ["Security"]
+-Security_Authentication_Identity = ["Security_Authentication"]
+-Security_Authentication_Identity_Core = ["Security_Authentication_Identity"]
+-Security_Authentication_OnlineId = ["Security_Authentication"]
+-Security_Authentication_Web = ["Security_Authentication"]
+-Security_Authentication_Web_Core = ["Security_Authentication_Web"]
+-Security_Authentication_Web_Provider = ["Security_Authentication_Web"]
+-Security_Authorization = ["Security"]
+-Security_Authorization_AppCapabilityAccess = ["Security_Authorization"]
+-Security_Credentials = ["Security"]
+-Security_Credentials_UI = ["Security_Credentials"]
+-Security_Cryptography = ["Security"]
+-Security_Cryptography_Certificates = ["Security_Cryptography"]
+-Security_Cryptography_Core = ["Security_Cryptography"]
+-Security_Cryptography_DataProtection = ["Security_Cryptography"]
+-Security_DataProtection = ["Security"]
+-Security_EnterpriseData = ["Security"]
+-Security_ExchangeActiveSyncProvisioning = ["Security"]
+-Security_Isolation = ["Security"]
+-Services = ["Foundation"]
+-Services_Maps = ["Services"]
+-Services_Maps_Guidance = ["Services_Maps"]
+-Services_Maps_LocalSearch = ["Services_Maps"]
+-Services_Maps_OfflineMaps = ["Services_Maps"]
+-Services_Store = ["Services"]
+-Services_TargetedContent = ["Services"]
+-Storage = ["Foundation"]
+-Storage_AccessCache = ["Storage"]
+-Storage_BulkAccess = ["Storage"]
+-Storage_Compression = ["Storage"]
+-Storage_FileProperties = ["Storage"]
+-Storage_Pickers = ["Storage"]
+-Storage_Pickers_Provider = ["Storage_Pickers"]
+-Storage_Provider = ["Storage"]
+-Storage_Search = ["Storage"]
+-Storage_Streams = ["Storage"]
+-System = ["Foundation"]
+-System_Diagnostics = ["System"]
+-System_Diagnostics_DevicePortal = ["System_Diagnostics"]
+-System_Diagnostics_Telemetry = ["System_Diagnostics"]
+-System_Diagnostics_TraceReporting = ["System_Diagnostics"]
+-System_Display = ["System"]
+-System_Implementation = ["System"]
+-System_Implementation_FileExplorer = ["System_Implementation"]
+-System_Inventory = ["System"]
+-System_Power = ["System"]
+-System_Profile = ["System"]
+-System_Profile_SystemManufacturers = ["System_Profile"]
+-System_RemoteDesktop = ["System"]
+-System_RemoteDesktop_Input = ["System_RemoteDesktop"]
+-System_RemoteDesktop_Provider = ["System_RemoteDesktop"]
+-System_RemoteSystems = ["System"]
+-System_Threading = ["System"]
+-System_Threading_Core = ["System_Threading"]
+-System_Update = ["System"]
+-System_UserProfile = ["System"]
+-UI = ["Foundation"]
+-UI_Accessibility = ["UI"]
+-UI_ApplicationSettings = ["UI"]
+-UI_Composition = ["UI"]
+-UI_Composition_Core = ["UI_Composition"]
+-UI_Composition_Desktop = ["UI_Composition"]
+-UI_Composition_Diagnostics = ["UI_Composition"]
+-UI_Composition_Effects = ["UI_Composition"]
+-UI_Composition_Interactions = ["UI_Composition"]
+-UI_Composition_Scenes = ["UI_Composition"]
+-UI_Core = ["UI"]
+-UI_Core_AnimationMetrics = ["UI_Core"]
+-UI_Core_Preview = ["UI_Core"]
+-UI_Input = ["UI"]
+-UI_Input_Core = ["UI_Input"]
+-UI_Input_Inking = ["UI_Input"]
+-UI_Input_Inking_Analysis = ["UI_Input_Inking"]
+-UI_Input_Inking_Core = ["UI_Input_Inking"]
+-UI_Input_Inking_Preview = ["UI_Input_Inking"]
+-UI_Input_Preview = ["UI_Input"]
+-UI_Input_Preview_Injection = ["UI_Input_Preview"]
+-UI_Input_Spatial = ["UI_Input"]
+-UI_Notifications = ["UI"]
+-UI_Notifications_Management = ["UI_Notifications"]
+-UI_Notifications_Preview = ["UI_Notifications"]
+-UI_Popups = ["UI"]
+-UI_Shell = ["UI"]
+-UI_StartScreen = ["UI"]
+-UI_Text = ["UI"]
+-UI_Text_Core = ["UI_Text"]
+-UI_UIAutomation = ["UI"]
+-UI_UIAutomation_Core = ["UI_UIAutomation"]
+-UI_ViewManagement = ["UI"]
+-UI_ViewManagement_Core = ["UI_ViewManagement"]
+-UI_WebUI = ["UI"]
+-UI_WebUI_Core = ["UI_WebUI"]
+-UI_WindowManagement = ["UI"]
+-UI_WindowManagement_Preview = ["UI_WindowManagement"]
+-Wdk = ["Win32_Foundation"]
+-Wdk_Devices = ["Wdk"]
+-Wdk_Devices_HumanInterfaceDevice = ["Wdk_Devices"]
+-Wdk_Foundation = ["Wdk"]
+-Wdk_Graphics = ["Wdk"]
+-Wdk_Graphics_Direct3D = ["Wdk_Graphics"]
+-Wdk_NetworkManagement = ["Wdk"]
+-Wdk_NetworkManagement_Ndis = ["Wdk_NetworkManagement"]
+-Wdk_NetworkManagement_WindowsFilteringPlatform = ["Wdk_NetworkManagement"]
+-Wdk_Storage = ["Wdk"]
+-Wdk_Storage_FileSystem = ["Wdk_Storage"]
+-Wdk_Storage_FileSystem_Minifilters = ["Wdk_Storage_FileSystem"]
+-Wdk_System = ["Wdk"]
+-Wdk_System_IO = ["Wdk_System"]
+-Wdk_System_OfflineRegistry = ["Wdk_System"]
+-Wdk_System_Registry = ["Wdk_System"]
+-Wdk_System_SystemInformation = ["Wdk_System"]
+-Wdk_System_SystemServices = ["Wdk_System"]
+-Wdk_System_Threading = ["Wdk_System"]
+-Web = ["Foundation"]
+-Web_AtomPub = ["Web"]
+-Web_Http = ["Web"]
+-Web_Http_Diagnostics = ["Web_Http"]
+-Web_Http_Filters = ["Web_Http"]
+-Web_Http_Headers = ["Web_Http"]
+-Web_Syndication = ["Web"]
+-Web_UI = ["Web"]
+-Web_UI_Interop = ["Web_UI"]
+-Win32 = ["Win32_Foundation"]
+-Win32_AI = ["Win32"]
+-Win32_AI_MachineLearning = ["Win32_AI"]
+-Win32_AI_MachineLearning_DirectML = ["Win32_AI_MachineLearning"]
+-Win32_AI_MachineLearning_WinML = ["Win32_AI_MachineLearning"]
+-Win32_Data = ["Win32"]
+-Win32_Data_HtmlHelp = ["Win32_Data"]
+-Win32_Data_RightsManagement = ["Win32_Data"]
+-Win32_Data_Xml = ["Win32_Data"]
+-Win32_Data_Xml_MsXml = ["Win32_Data_Xml"]
+-Win32_Data_Xml_XmlLite = ["Win32_Data_Xml"]
+-Win32_Devices = ["Win32"]
+-Win32_Devices_AllJoyn = ["Win32_Devices"]
+-Win32_Devices_BiometricFramework = ["Win32_Devices"]
+-Win32_Devices_Bluetooth = ["Win32_Devices"]
+-Win32_Devices_Communication = ["Win32_Devices"]
+-Win32_Devices_DeviceAccess = ["Win32_Devices"]
+-Win32_Devices_DeviceAndDriverInstallation = ["Win32_Devices"]
+-Win32_Devices_DeviceQuery = ["Win32_Devices"]
+-Win32_Devices_Display = ["Win32_Devices"]
+-Win32_Devices_Enumeration = ["Win32_Devices"]
+-Win32_Devices_Enumeration_Pnp = ["Win32_Devices_Enumeration"]
+-Win32_Devices_Fax = ["Win32_Devices"]
+-Win32_Devices_FunctionDiscovery = ["Win32_Devices"]
+-Win32_Devices_Geolocation = ["Win32_Devices"]
+-Win32_Devices_HumanInterfaceDevice = ["Win32_Devices"]
+-Win32_Devices_ImageAcquisition = ["Win32_Devices"]
+-Win32_Devices_PortableDevices = ["Win32_Devices"]
+-Win32_Devices_Properties = ["Win32_Devices"]
+-Win32_Devices_Pwm = ["Win32_Devices"]
+-Win32_Devices_Sensors = ["Win32_Devices"]
+-Win32_Devices_SerialCommunication = ["Win32_Devices"]
+-Win32_Devices_Tapi = ["Win32_Devices"]
+-Win32_Devices_Usb = ["Win32_Devices"]
+-Win32_Devices_WebServicesOnDevices = ["Win32_Devices"]
+-Win32_Foundation = ["Win32"]
+-Win32_Gaming = ["Win32"]
+-Win32_Globalization = ["Win32"]
+-Win32_Graphics = ["Win32"]
+-Win32_Graphics_CompositionSwapchain = ["Win32_Graphics"]
+-Win32_Graphics_DXCore = ["Win32_Graphics"]
+-Win32_Graphics_Direct2D = ["Win32_Graphics"]
+-Win32_Graphics_Direct2D_Common = ["Win32_Graphics_Direct2D"]
+-Win32_Graphics_Direct3D = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D10 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D11 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D11on12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D9 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D9on12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D_Dxc = ["Win32_Graphics_Direct3D"]
+-Win32_Graphics_Direct3D_Fxc = ["Win32_Graphics_Direct3D"]
+-Win32_Graphics_DirectComposition = ["Win32_Graphics"]
+-Win32_Graphics_DirectDraw = ["Win32_Graphics"]
+-Win32_Graphics_DirectManipulation = ["Win32_Graphics"]
+-Win32_Graphics_DirectWrite = ["Win32_Graphics"]
+-Win32_Graphics_Dwm = ["Win32_Graphics"]
+-Win32_Graphics_Dxgi = ["Win32_Graphics"]
+-Win32_Graphics_Dxgi_Common = ["Win32_Graphics_Dxgi"]
+-Win32_Graphics_Gdi = ["Win32_Graphics"]
+-Win32_Graphics_GdiPlus = ["Win32_Graphics"]
+-Win32_Graphics_Hlsl = ["Win32_Graphics"]
+-Win32_Graphics_Imaging = ["Win32_Graphics"]
+-Win32_Graphics_Imaging_D2D = ["Win32_Graphics_Imaging"]
+-Win32_Graphics_OpenGL = ["Win32_Graphics"]
+-Win32_Graphics_Printing = ["Win32_Graphics"]
+-Win32_Graphics_Printing_PrintTicket = ["Win32_Graphics_Printing"]
+-Win32_Management = ["Win32"]
+-Win32_Management_MobileDeviceManagementRegistration = ["Win32_Management"]
+-Win32_Media = ["Win32"]
+-Win32_Media_Audio = ["Win32_Media"]
+-Win32_Media_Audio_Apo = ["Win32_Media_Audio"]
+-Win32_Media_Audio_DirectMusic = ["Win32_Media_Audio"]
+-Win32_Media_Audio_DirectSound = ["Win32_Media_Audio"]
+-Win32_Media_Audio_Endpoints = ["Win32_Media_Audio"]
+-Win32_Media_Audio_XAudio2 = ["Win32_Media_Audio"]
+-Win32_Media_DeviceManager = ["Win32_Media"]
+-Win32_Media_DirectShow = ["Win32_Media"]
+-Win32_Media_DirectShow_Tv = ["Win32_Media_DirectShow"]
+-Win32_Media_DirectShow_Xml = ["Win32_Media_DirectShow"]
+-Win32_Media_DxMediaObjects = ["Win32_Media"]
+-Win32_Media_KernelStreaming = ["Win32_Media"]
+-Win32_Media_LibrarySharingServices = ["Win32_Media"]
+-Win32_Media_MediaFoundation = ["Win32_Media"]
+-Win32_Media_MediaPlayer = ["Win32_Media"]
+-Win32_Media_Multimedia = ["Win32_Media"]
+-Win32_Media_PictureAcquisition = ["Win32_Media"]
+-Win32_Media_Speech = ["Win32_Media"]
+-Win32_Media_Streaming = ["Win32_Media"]
+-Win32_Media_WindowsMediaFormat = ["Win32_Media"]
+-Win32_NetworkManagement = ["Win32"]
+-Win32_NetworkManagement_Dhcp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Dns = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_InternetConnectionWizard = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_IpHelper = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_MobileBroadband = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Multicast = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Ndis = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetBios = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetManagement = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetShell = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetworkDiagnosticsFramework = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetworkPolicyServer = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_P2P = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_QoS = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Rras = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Snmp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WNet = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WebDav = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WiFi = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsConnectNow = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsConnectionManager = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFilteringPlatform = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFirewall = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsNetworkVirtualization = ["Win32_NetworkManagement"]
+-Win32_Networking = ["Win32"]
+-Win32_Networking_ActiveDirectory = ["Win32_Networking"]
+-Win32_Networking_BackgroundIntelligentTransferService = ["Win32_Networking"]
+-Win32_Networking_Clustering = ["Win32_Networking"]
+-Win32_Networking_HttpServer = ["Win32_Networking"]
+-Win32_Networking_Ldap = ["Win32_Networking"]
+-Win32_Networking_NetworkListManager = ["Win32_Networking"]
+-Win32_Networking_RemoteDifferentialCompression = ["Win32_Networking"]
+-Win32_Networking_WebSocket = ["Win32_Networking"]
+-Win32_Networking_WinHttp = ["Win32_Networking"]
+-Win32_Networking_WinInet = ["Win32_Networking"]
+-Win32_Networking_WinSock = ["Win32_Networking"]
+-Win32_Networking_WindowsWebServices = ["Win32_Networking"]
+-Win32_Security = ["Win32"]
+-Win32_Security_AppLocker = ["Win32_Security"]
+-Win32_Security_Authentication = ["Win32_Security"]
+-Win32_Security_Authentication_Identity = ["Win32_Security_Authentication"]
+-Win32_Security_Authentication_Identity_Provider = ["Win32_Security_Authentication_Identity"]
+-Win32_Security_Authorization = ["Win32_Security"]
+-Win32_Security_Authorization_UI = ["Win32_Security_Authorization"]
+-Win32_Security_ConfigurationSnapin = ["Win32_Security"]
+-Win32_Security_Credentials = ["Win32_Security"]
+-Win32_Security_Cryptography = ["Win32_Security"]
+-Win32_Security_Cryptography_Catalog = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Certificates = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Sip = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_UI = ["Win32_Security_Cryptography"]
+-Win32_Security_DiagnosticDataQuery = ["Win32_Security"]
+-Win32_Security_DirectoryServices = ["Win32_Security"]
+-Win32_Security_EnterpriseData = ["Win32_Security"]
+-Win32_Security_ExtensibleAuthenticationProtocol = ["Win32_Security"]
+-Win32_Security_Isolation = ["Win32_Security"]
+-Win32_Security_LicenseProtection = ["Win32_Security"]
+-Win32_Security_NetworkAccessProtection = ["Win32_Security"]
+-Win32_Security_Tpm = ["Win32_Security"]
+-Win32_Security_WinTrust = ["Win32_Security"]
+-Win32_Security_WinWlx = ["Win32_Security"]
+-Win32_Storage = ["Win32"]
+-Win32_Storage_Cabinets = ["Win32_Storage"]
+-Win32_Storage_CloudFilters = ["Win32_Storage"]
+-Win32_Storage_Compression = ["Win32_Storage"]
+-Win32_Storage_DataDeduplication = ["Win32_Storage"]
+-Win32_Storage_DistributedFileSystem = ["Win32_Storage"]
+-Win32_Storage_EnhancedStorage = ["Win32_Storage"]
+-Win32_Storage_FileHistory = ["Win32_Storage"]
+-Win32_Storage_FileServerResourceManager = ["Win32_Storage"]
+-Win32_Storage_FileSystem = ["Win32_Storage"]
+-Win32_Storage_Imapi = ["Win32_Storage"]
+-Win32_Storage_IndexServer = ["Win32_Storage"]
+-Win32_Storage_InstallableFileSystems = ["Win32_Storage"]
+-Win32_Storage_IscsiDisc = ["Win32_Storage"]
+-Win32_Storage_Jet = ["Win32_Storage"]
+-Win32_Storage_Nvme = ["Win32_Storage"]
+-Win32_Storage_OfflineFiles = ["Win32_Storage"]
+-Win32_Storage_OperationRecorder = ["Win32_Storage"]
+-Win32_Storage_Packaging = ["Win32_Storage"]
+-Win32_Storage_Packaging_Appx = ["Win32_Storage_Packaging"]
+-Win32_Storage_Packaging_Opc = ["Win32_Storage_Packaging"]
+-Win32_Storage_ProjectedFileSystem = ["Win32_Storage"]
+-Win32_Storage_StructuredStorage = ["Win32_Storage"]
+-Win32_Storage_Vhd = ["Win32_Storage"]
+-Win32_Storage_VirtualDiskService = ["Win32_Storage"]
+-Win32_Storage_Vss = ["Win32_Storage"]
+-Win32_Storage_Xps = ["Win32_Storage"]
+-Win32_Storage_Xps_Printing = ["Win32_Storage_Xps"]
+-Win32_System = ["Win32"]
+-Win32_System_AddressBook = ["Win32_System"]
+-Win32_System_Antimalware = ["Win32_System"]
+-Win32_System_ApplicationInstallationAndServicing = ["Win32_System"]
+-Win32_System_ApplicationVerifier = ["Win32_System"]
+-Win32_System_AssessmentTool = ["Win32_System"]
+-Win32_System_ClrHosting = ["Win32_System"]
+-Win32_System_Com = ["Win32_System"]
+-Win32_System_Com_CallObj = ["Win32_System_Com"]
+-Win32_System_Com_ChannelCredentials = ["Win32_System_Com"]
+-Win32_System_Com_Events = ["Win32_System_Com"]
+-Win32_System_Com_Marshal = ["Win32_System_Com"]
+-Win32_System_Com_StructuredStorage = ["Win32_System_Com"]
+-Win32_System_Com_UI = ["Win32_System_Com"]
+-Win32_System_Com_Urlmon = ["Win32_System_Com"]
+-Win32_System_ComponentServices = ["Win32_System"]
+-Win32_System_Console = ["Win32_System"]
+-Win32_System_Contacts = ["Win32_System"]
+-Win32_System_CorrelationVector = ["Win32_System"]
+-Win32_System_DataExchange = ["Win32_System"]
+-Win32_System_DeploymentServices = ["Win32_System"]
+-Win32_System_DesktopSharing = ["Win32_System"]
+-Win32_System_DeveloperLicensing = ["Win32_System"]
+-Win32_System_Diagnostics = ["Win32_System"]
+-Win32_System_Diagnostics_Ceip = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ClrProfiling = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug_ActiveScript = ["Win32_System_Diagnostics_Debug"]
+-Win32_System_Diagnostics_Debug_Extensions = ["Win32_System_Diagnostics_Debug"]
+-Win32_System_Diagnostics_Etw = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ProcessSnapshotting = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ToolHelp = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_TraceLogging = ["Win32_System_Diagnostics"]
+-Win32_System_DistributedTransactionCoordinator = ["Win32_System"]
+-Win32_System_Environment = ["Win32_System"]
+-Win32_System_ErrorReporting = ["Win32_System"]
+-Win32_System_EventCollector = ["Win32_System"]
+-Win32_System_EventLog = ["Win32_System"]
+-Win32_System_EventNotificationService = ["Win32_System"]
+-Win32_System_GroupPolicy = ["Win32_System"]
+-Win32_System_HostCompute = ["Win32_System"]
+-Win32_System_HostComputeNetwork = ["Win32_System"]
+-Win32_System_HostComputeSystem = ["Win32_System"]
+-Win32_System_Hypervisor = ["Win32_System"]
+-Win32_System_IO = ["Win32_System"]
+-Win32_System_Iis = ["Win32_System"]
+-Win32_System_Ioctl = ["Win32_System"]
+-Win32_System_JobObjects = ["Win32_System"]
+-Win32_System_Js = ["Win32_System"]
+-Win32_System_Kernel = ["Win32_System"]
+-Win32_System_LibraryLoader = ["Win32_System"]
+-Win32_System_Mailslots = ["Win32_System"]
+-Win32_System_Mapi = ["Win32_System"]
+-Win32_System_Memory = ["Win32_System"]
+-Win32_System_Memory_NonVolatile = ["Win32_System_Memory"]
+-Win32_System_MessageQueuing = ["Win32_System"]
+-Win32_System_MixedReality = ["Win32_System"]
+-Win32_System_Mmc = ["Win32_System"]
+-Win32_System_Ole = ["Win32_System"]
+-Win32_System_ParentalControls = ["Win32_System"]
+-Win32_System_PasswordManagement = ["Win32_System"]
+-Win32_System_Performance = ["Win32_System"]
+-Win32_System_Performance_HardwareCounterProfiling = ["Win32_System_Performance"]
+-Win32_System_Pipes = ["Win32_System"]
+-Win32_System_Power = ["Win32_System"]
+-Win32_System_ProcessStatus = ["Win32_System"]
+-Win32_System_RealTimeCommunications = ["Win32_System"]
+-Win32_System_Recovery = ["Win32_System"]
+-Win32_System_Registry = ["Win32_System"]
+-Win32_System_RemoteAssistance = ["Win32_System"]
+-Win32_System_RemoteDesktop = ["Win32_System"]
+-Win32_System_RemoteManagement = ["Win32_System"]
+-Win32_System_RestartManager = ["Win32_System"]
+-Win32_System_Restore = ["Win32_System"]
+-Win32_System_Rpc = ["Win32_System"]
+-Win32_System_Search = ["Win32_System"]
+-Win32_System_Search_Common = ["Win32_System_Search"]
+-Win32_System_SecurityCenter = ["Win32_System"]
+-Win32_System_ServerBackup = ["Win32_System"]
+-Win32_System_Services = ["Win32_System"]
+-Win32_System_SettingsManagementInfrastructure = ["Win32_System"]
+-Win32_System_SetupAndMigration = ["Win32_System"]
+-Win32_System_Shutdown = ["Win32_System"]
+-Win32_System_SideShow = ["Win32_System"]
+-Win32_System_StationsAndDesktops = ["Win32_System"]
+-Win32_System_SubsystemForLinux = ["Win32_System"]
+-Win32_System_SystemInformation = ["Win32_System"]
+-Win32_System_SystemServices = ["Win32_System"]
+-Win32_System_TaskScheduler = ["Win32_System"]
+-Win32_System_Threading = ["Win32_System"]
+-Win32_System_Time = ["Win32_System"]
+-Win32_System_TpmBaseServices = ["Win32_System"]
+-Win32_System_TransactionServer = ["Win32_System"]
+-Win32_System_UpdateAgent = ["Win32_System"]
+-Win32_System_UpdateAssessment = ["Win32_System"]
+-Win32_System_UserAccessLogging = ["Win32_System"]
+-Win32_System_Variant = ["Win32_System"]
+-Win32_System_VirtualDosMachines = ["Win32_System"]
+-Win32_System_WinRT = ["Win32_System"]
+-Win32_System_WinRT_AllJoyn = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Composition = ["Win32_System_WinRT"]
+-Win32_System_WinRT_CoreInputView = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Direct3D11 = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Display = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Graphics = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Graphics_Capture = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Graphics_Direct2D = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Graphics_Imaging = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Holographic = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Isolation = ["Win32_System_WinRT"]
+-Win32_System_WinRT_ML = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Media = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Metadata = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Pdf = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Printing = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Shell = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Storage = ["Win32_System_WinRT"]
+-Win32_System_WindowsProgramming = ["Win32_System"]
+-Win32_System_WindowsSync = ["Win32_System"]
+-Win32_System_Wmi = ["Win32_System"]
+-Win32_UI = ["Win32"]
+-Win32_UI_Accessibility = ["Win32_UI"]
+-Win32_UI_Animation = ["Win32_UI"]
+-Win32_UI_ColorSystem = ["Win32_UI"]
+-Win32_UI_Controls = ["Win32_UI"]
+-Win32_UI_Controls_Dialogs = ["Win32_UI_Controls"]
+-Win32_UI_Controls_RichEdit = ["Win32_UI_Controls"]
+-Win32_UI_HiDpi = ["Win32_UI"]
+-Win32_UI_Input = ["Win32_UI"]
+-Win32_UI_Input_Ime = ["Win32_UI_Input"]
+-Win32_UI_Input_Ink = ["Win32_UI_Input"]
+-Win32_UI_Input_KeyboardAndMouse = ["Win32_UI_Input"]
+-Win32_UI_Input_Pointer = ["Win32_UI_Input"]
+-Win32_UI_Input_Radial = ["Win32_UI_Input"]
+-Win32_UI_Input_Touch = ["Win32_UI_Input"]
+-Win32_UI_Input_XboxController = ["Win32_UI_Input"]
+-Win32_UI_InteractionContext = ["Win32_UI"]
+-Win32_UI_LegacyWindowsEnvironmentFeatures = ["Win32_UI"]
+-Win32_UI_Magnification = ["Win32_UI"]
+-Win32_UI_Notifications = ["Win32_UI"]
+-Win32_UI_Ribbon = ["Win32_UI"]
+-Win32_UI_Shell = ["Win32_UI"]
+-Win32_UI_Shell_Common = ["Win32_UI_Shell"]
+-Win32_UI_Shell_PropertiesSystem = ["Win32_UI_Shell"]
+-Win32_UI_TabletPC = ["Win32_UI"]
+-Win32_UI_TextServices = ["Win32_UI"]
+-Win32_UI_WindowsAndMessaging = ["Win32_UI"]
+-Win32_UI_Wpf = ["Win32_UI"]
+-Win32_Web = ["Win32"]
+-Win32_Web_InternetExplorer = ["Win32_Web"]
++Foundation_Collections = []
++Foundation_Diagnostics = []
++Foundation_Metadata = []
++Foundation_Numerics = []
++Gaming = []
++Gaming_Input = []
++Gaming_Input_Custom = []
++Gaming_Input_ForceFeedback = []
++Gaming_Input_Preview = []
++Gaming_Preview = []
++Gaming_Preview_GamesEnumeration = []
++Gaming_UI = []
++Gaming_XboxLive = []
++Gaming_XboxLive_Storage = []
++Globalization = []
++Globalization_Collation = []
++Globalization_DateTimeFormatting = []
++Globalization_Fonts = []
++Globalization_NumberFormatting = []
++Globalization_PhoneNumberFormatting = []
++Graphics = []
++Graphics_Capture = []
++Graphics_DirectX = []
++Graphics_DirectX_Direct3D11 = []
++Graphics_Display = []
++Graphics_Display_Core = []
++Graphics_Effects = []
++Graphics_Holographic = []
++Graphics_Imaging = []
++Graphics_Printing = []
++Graphics_Printing3D = []
++Graphics_Printing_OptionDetails = []
++Graphics_Printing_PrintSupport = []
++Graphics_Printing_PrintTicket = []
++Graphics_Printing_Workflow = []
++Management = []
++Management_Core = []
++Management_Deployment = []
++Management_Deployment_Preview = []
++Management_Policies = []
++Management_Update = []
++Management_Workplace = []
++Media = []
++Media_AppBroadcasting = []
++Media_AppRecording = []
++Media_Audio = []
++Media_Capture = []
++Media_Capture_Core = []
++Media_Capture_Frames = []
++Media_Casting = []
++Media_ClosedCaptioning = []
++Media_ContentRestrictions = []
++Media_Control = []
++Media_Core = []
++Media_Core_Preview = []
++Media_Devices = []
++Media_Devices_Core = []
++Media_DialProtocol = []
++Media_Editing = []
++Media_Effects = []
++Media_FaceAnalysis = []
++Media_Import = []
++Media_MediaProperties = []
++Media_Miracast = []
++Media_Ocr = []
++Media_PlayTo = []
++Media_Playback = []
++Media_Playlists = []
++Media_Protection = []
++Media_Protection_PlayReady = []
++Media_Render = []
++Media_SpeechRecognition = []
++Media_SpeechSynthesis = []
++Media_Streaming = []
++Media_Streaming_Adaptive = []
++Media_Transcoding = []
++Networking = []
++Networking_BackgroundTransfer = []
++Networking_Connectivity = []
++Networking_NetworkOperators = []
++Networking_Proximity = []
++Networking_PushNotifications = []
++Networking_ServiceDiscovery = []
++Networking_ServiceDiscovery_Dnssd = []
++Networking_Sockets = []
++Networking_Vpn = []
++Networking_XboxLive = []
++Perception = []
++Perception_Automation = []
++Perception_Automation_Core = []
++Perception_People = []
++Perception_Spatial = []
++Perception_Spatial_Preview = []
++Perception_Spatial_Surfaces = []
++Phone = []
++Phone_ApplicationModel = []
++Phone_Devices = []
++Phone_Devices_Notification = []
++Phone_Devices_Power = []
++Phone_Management = []
++Phone_Management_Deployment = []
++Phone_Media = []
++Phone_Media_Devices = []
++Phone_Notification = []
++Phone_Notification_Management = []
++Phone_PersonalInformation = []
++Phone_PersonalInformation_Provisioning = []
++Phone_Speech = []
++Phone_Speech_Recognition = []
++Phone_StartScreen = []
++Phone_System = []
++Phone_System_Power = []
++Phone_System_Profile = []
++Phone_System_UserProfile = []
++Phone_System_UserProfile_GameServices = []
++Phone_System_UserProfile_GameServices_Core = []
++Phone_UI = []
++Phone_UI_Input = []
++Security = []
++Security_Authentication = []
++Security_Authentication_Identity = []
++Security_Authentication_Identity_Core = []
++Security_Authentication_OnlineId = []
++Security_Authentication_Web = []
++Security_Authentication_Web_Core = []
++Security_Authentication_Web_Provider = []
++Security_Authorization = []
++Security_Authorization_AppCapabilityAccess = []
++Security_Credentials = []
++Security_Credentials_UI = []
++Security_Cryptography = []
++Security_Cryptography_Certificates = []
++Security_Cryptography_Core = []
++Security_Cryptography_DataProtection = []
++Security_DataProtection = []
++Security_EnterpriseData = []
++Security_ExchangeActiveSyncProvisioning = []
++Security_Isolation = []
++Services = []
++Services_Maps = []
++Services_Maps_Guidance = []
++Services_Maps_LocalSearch = []
++Services_Maps_OfflineMaps = []
++Services_Store = []
++Services_TargetedContent = []
++Storage = []
++Storage_AccessCache = []
++Storage_BulkAccess = []
++Storage_Compression = []
++Storage_FileProperties = []
++Storage_Pickers = []
++Storage_Pickers_Provider = []
++Storage_Provider = []
++Storage_Search = []
++Storage_Streams = []
++System = []
++System_Diagnostics = []
++System_Diagnostics_DevicePortal = []
++System_Diagnostics_Telemetry = []
++System_Diagnostics_TraceReporting = []
++System_Display = []
++System_Implementation = []
++System_Implementation_FileExplorer = []
++System_Inventory = []
++System_Power = []
++System_Profile = []
++System_Profile_SystemManufacturers = []
++System_RemoteDesktop = []
++System_RemoteDesktop_Input = []
++System_RemoteDesktop_Provider = []
++System_RemoteSystems = []
++System_Threading = []
++System_Threading_Core = []
++System_Update = []
++System_UserProfile = []
++UI = []
++UI_Accessibility = []
++UI_ApplicationSettings = []
++UI_Composition = []
++UI_Composition_Core = []
++UI_Composition_Desktop = []
++UI_Composition_Diagnostics = []
++UI_Composition_Effects = []
++UI_Composition_Interactions = []
++UI_Composition_Scenes = []
++UI_Core = []
++UI_Core_AnimationMetrics = []
++UI_Core_Preview = []
++UI_Input = []
++UI_Input_Core = []
++UI_Input_Inking = []
++UI_Input_Inking_Analysis = []
++UI_Input_Inking_Core = []
++UI_Input_Inking_Preview = []
++UI_Input_Preview = []
++UI_Input_Preview_Injection = []
++UI_Input_Spatial = []
++UI_Notifications = []
++UI_Notifications_Management = []
++UI_Notifications_Preview = []
++UI_Popups = []
++UI_Shell = []
++UI_StartScreen = []
++UI_Text = []
++UI_Text_Core = []
++UI_UIAutomation = []
++UI_UIAutomation_Core = []
++UI_ViewManagement = []
++UI_ViewManagement_Core = []
++UI_WebUI = []
++UI_WebUI_Core = []
++UI_WindowManagement = []
++UI_WindowManagement_Preview = []
++Wdk = []
++Wdk_Devices = []
++Wdk_Devices_HumanInterfaceDevice = []
++Wdk_Foundation = []
++Wdk_Graphics = []
++Wdk_Graphics_Direct3D = []
++Wdk_NetworkManagement = []
++Wdk_NetworkManagement_Ndis = []
++Wdk_NetworkManagement_WindowsFilteringPlatform = []
++Wdk_Storage = []
++Wdk_Storage_FileSystem = []
++Wdk_Storage_FileSystem_Minifilters = []
++Wdk_System = []
++Wdk_System_IO = []
++Wdk_System_OfflineRegistry = []
++Wdk_System_Registry = []
++Wdk_System_SystemInformation = []
++Wdk_System_SystemServices = []
++Wdk_System_Threading = []
++Web = []
++Web_AtomPub = []
++Web_Http = []
++Web_Http_Diagnostics = []
++Web_Http_Filters = []
++Web_Http_Headers = []
++Web_Syndication = []
++Web_UI = []
++Web_UI_Interop = []
++Win32 = []
++Win32_AI = []
++Win32_AI_MachineLearning = []
++Win32_AI_MachineLearning_DirectML = []
++Win32_AI_MachineLearning_WinML = []
++Win32_Data = []
++Win32_Data_HtmlHelp = []
++Win32_Data_RightsManagement = []
++Win32_Data_Xml = []
++Win32_Data_Xml_MsXml = []
++Win32_Data_Xml_XmlLite = []
++Win32_Devices = []
++Win32_Devices_AllJoyn = []
++Win32_Devices_BiometricFramework = []
++Win32_Devices_Bluetooth = []
++Win32_Devices_Communication = []
++Win32_Devices_DeviceAccess = []
++Win32_Devices_DeviceAndDriverInstallation = []
++Win32_Devices_DeviceQuery = []
++Win32_Devices_Display = []
++Win32_Devices_Enumeration = []
++Win32_Devices_Enumeration_Pnp = []
++Win32_Devices_Fax = []
++Win32_Devices_FunctionDiscovery = []
++Win32_Devices_Geolocation = []
++Win32_Devices_HumanInterfaceDevice = []
++Win32_Devices_ImageAcquisition = []
++Win32_Devices_PortableDevices = []
++Win32_Devices_Properties = []
++Win32_Devices_Pwm = []
++Win32_Devices_Sensors = []
++Win32_Devices_SerialCommunication = []
++Win32_Devices_Tapi = []
++Win32_Devices_Usb = []
++Win32_Devices_WebServicesOnDevices = []
++Win32_Foundation = []
++Win32_Gaming = []
++Win32_Globalization = []
++Win32_Graphics = []
++Win32_Graphics_CompositionSwapchain = []
++Win32_Graphics_DXCore = []
++Win32_Graphics_Direct2D = []
++Win32_Graphics_Direct2D_Common = []
++Win32_Graphics_Direct3D = []
++Win32_Graphics_Direct3D10 = []
++Win32_Graphics_Direct3D11 = []
++Win32_Graphics_Direct3D11on12 = []
++Win32_Graphics_Direct3D12 = []
++Win32_Graphics_Direct3D9 = []
++Win32_Graphics_Direct3D9on12 = []
++Win32_Graphics_Direct3D_Dxc = []
++Win32_Graphics_Direct3D_Fxc = []
++Win32_Graphics_DirectComposition = []
++Win32_Graphics_DirectDraw = []
++Win32_Graphics_DirectManipulation = []
++Win32_Graphics_DirectWrite = []
++Win32_Graphics_Dwm = []
++Win32_Graphics_Dxgi = []
++Win32_Graphics_Dxgi_Common = []
++Win32_Graphics_Gdi = []
++Win32_Graphics_GdiPlus = []
++Win32_Graphics_Hlsl = []
++Win32_Graphics_Imaging = []
++Win32_Graphics_Imaging_D2D = []
++Win32_Graphics_OpenGL = []
++Win32_Graphics_Printing = []
++Win32_Graphics_Printing_PrintTicket = []
++Win32_Management = []
++Win32_Management_MobileDeviceManagementRegistration = []
++Win32_Media = []
++Win32_Media_Audio = []
++Win32_Media_Audio_Apo = []
++Win32_Media_Audio_DirectMusic = []
++Win32_Media_Audio_DirectSound = []
++Win32_Media_Audio_Endpoints = []
++Win32_Media_Audio_XAudio2 = []
++Win32_Media_DeviceManager = []
++Win32_Media_DirectShow = []
++Win32_Media_DirectShow_Tv = []
++Win32_Media_DirectShow_Xml = []
++Win32_Media_DxMediaObjects = []
++Win32_Media_KernelStreaming = []
++Win32_Media_LibrarySharingServices = []
++Win32_Media_MediaFoundation = []
++Win32_Media_MediaPlayer = []
++Win32_Media_Multimedia = []
++Win32_Media_PictureAcquisition = []
++Win32_Media_Speech = []
++Win32_Media_Streaming = []
++Win32_Media_WindowsMediaFormat = []
++Win32_NetworkManagement = []
++Win32_NetworkManagement_Dhcp = []
++Win32_NetworkManagement_Dns = []
++Win32_NetworkManagement_InternetConnectionWizard = []
++Win32_NetworkManagement_IpHelper = []
++Win32_NetworkManagement_MobileBroadband = []
++Win32_NetworkManagement_Multicast = []
++Win32_NetworkManagement_Ndis = []
++Win32_NetworkManagement_NetBios = []
++Win32_NetworkManagement_NetManagement = []
++Win32_NetworkManagement_NetShell = []
++Win32_NetworkManagement_NetworkDiagnosticsFramework = []
++Win32_NetworkManagement_NetworkPolicyServer = []
++Win32_NetworkManagement_P2P = []
++Win32_NetworkManagement_QoS = []
++Win32_NetworkManagement_Rras = []
++Win32_NetworkManagement_Snmp = []
++Win32_NetworkManagement_WNet = []
++Win32_NetworkManagement_WebDav = []
++Win32_NetworkManagement_WiFi = []
++Win32_NetworkManagement_WindowsConnectNow = []
++Win32_NetworkManagement_WindowsConnectionManager = []
++Win32_NetworkManagement_WindowsFilteringPlatform = []
++Win32_NetworkManagement_WindowsFirewall = []
++Win32_NetworkManagement_WindowsNetworkVirtualization = []
++Win32_Networking = []
++Win32_Networking_ActiveDirectory = []
++Win32_Networking_BackgroundIntelligentTransferService = []
++Win32_Networking_Clustering = []
++Win32_Networking_HttpServer = []
++Win32_Networking_Ldap = []
++Win32_Networking_NetworkListManager = []
++Win32_Networking_RemoteDifferentialCompression = []
++Win32_Networking_WebSocket = []
++Win32_Networking_WinHttp = []
++Win32_Networking_WinInet = []
++Win32_Networking_WinSock = []
++Win32_Networking_WindowsWebServices = []
++Win32_Security = []
++Win32_Security_AppLocker = []
++Win32_Security_Authentication = []
++Win32_Security_Authentication_Identity = []
++Win32_Security_Authentication_Identity_Provider = []
++Win32_Security_Authorization = []
++Win32_Security_Authorization_UI = []
++Win32_Security_ConfigurationSnapin = []
++Win32_Security_Credentials = []
++Win32_Security_Cryptography = []
++Win32_Security_Cryptography_Catalog = []
++Win32_Security_Cryptography_Certificates = []
++Win32_Security_Cryptography_Sip = []
++Win32_Security_Cryptography_UI = []
++Win32_Security_DiagnosticDataQuery = []
++Win32_Security_DirectoryServices = []
++Win32_Security_EnterpriseData = []
++Win32_Security_ExtensibleAuthenticationProtocol = []
++Win32_Security_Isolation = []
++Win32_Security_LicenseProtection = []
++Win32_Security_NetworkAccessProtection = []
++Win32_Security_Tpm = []
++Win32_Security_WinTrust = []
++Win32_Security_WinWlx = []
++Win32_Storage = []
++Win32_Storage_Cabinets = []
++Win32_Storage_CloudFilters = []
++Win32_Storage_Compression = []
++Win32_Storage_DataDeduplication = []
++Win32_Storage_DistributedFileSystem = []
++Win32_Storage_EnhancedStorage = []
++Win32_Storage_FileHistory = []
++Win32_Storage_FileServerResourceManager = []
++Win32_Storage_FileSystem = []
++Win32_Storage_Imapi = []
++Win32_Storage_IndexServer = []
++Win32_Storage_InstallableFileSystems = []
++Win32_Storage_IscsiDisc = []
++Win32_Storage_Jet = []
++Win32_Storage_Nvme = []
++Win32_Storage_OfflineFiles = []
++Win32_Storage_OperationRecorder = []
++Win32_Storage_Packaging = []
++Win32_Storage_Packaging_Appx = []
++Win32_Storage_Packaging_Opc = []
++Win32_Storage_ProjectedFileSystem = []
++Win32_Storage_StructuredStorage = []
++Win32_Storage_Vhd = []
++Win32_Storage_VirtualDiskService = []
++Win32_Storage_Vss = []
++Win32_Storage_Xps = []
++Win32_Storage_Xps_Printing = []
++Win32_System = []
++Win32_System_AddressBook = []
++Win32_System_Antimalware = []
++Win32_System_ApplicationInstallationAndServicing = []
++Win32_System_ApplicationVerifier = []
++Win32_System_AssessmentTool = []
++Win32_System_ClrHosting = []
++Win32_System_Com = []
++Win32_System_Com_CallObj = []
++Win32_System_Com_ChannelCredentials = []
++Win32_System_Com_Events = []
++Win32_System_Com_Marshal = []
++Win32_System_Com_StructuredStorage = []
++Win32_System_Com_UI = []
++Win32_System_Com_Urlmon = []
++Win32_System_ComponentServices = []
++Win32_System_Console = []
++Win32_System_Contacts = []
++Win32_System_CorrelationVector = []
++Win32_System_DataExchange = []
++Win32_System_DeploymentServices = []
++Win32_System_DesktopSharing = []
++Win32_System_DeveloperLicensing = []
++Win32_System_Diagnostics = []
++Win32_System_Diagnostics_Ceip = []
++Win32_System_Diagnostics_ClrProfiling = []
++Win32_System_Diagnostics_Debug = []
++Win32_System_Diagnostics_Debug_ActiveScript = []
++Win32_System_Diagnostics_Debug_Extensions = []
++Win32_System_Diagnostics_Etw = []
++Win32_System_Diagnostics_ProcessSnapshotting = []
++Win32_System_Diagnostics_ToolHelp = []
++Win32_System_Diagnostics_TraceLogging = []
++Win32_System_DistributedTransactionCoordinator = []
++Win32_System_Environment = []
++Win32_System_ErrorReporting = []
++Win32_System_EventCollector = []
++Win32_System_EventLog = []
++Win32_System_EventNotificationService = []
++Win32_System_GroupPolicy = []
++Win32_System_HostCompute = []
++Win32_System_HostComputeNetwork = []
++Win32_System_HostComputeSystem = []
++Win32_System_Hypervisor = []
++Win32_System_IO = []
++Win32_System_Iis = []
++Win32_System_Ioctl = []
++Win32_System_JobObjects = []
++Win32_System_Js = []
++Win32_System_Kernel = []
++Win32_System_LibraryLoader = []
++Win32_System_Mailslots = []
++Win32_System_Mapi = []
++Win32_System_Memory = []
++Win32_System_Memory_NonVolatile = []
++Win32_System_MessageQueuing = []
++Win32_System_MixedReality = []
++Win32_System_Mmc = []
++Win32_System_Ole = []
++Win32_System_ParentalControls = []
++Win32_System_PasswordManagement = []
++Win32_System_Performance = []
++Win32_System_Performance_HardwareCounterProfiling = []
++Win32_System_Pipes = []
++Win32_System_Power = []
++Win32_System_ProcessStatus = []
++Win32_System_RealTimeCommunications = []
++Win32_System_Recovery = []
++Win32_System_Registry = []
++Win32_System_RemoteAssistance = []
++Win32_System_RemoteDesktop = []
++Win32_System_RemoteManagement = []
++Win32_System_RestartManager = []
++Win32_System_Restore = []
++Win32_System_Rpc = []
++Win32_System_Search = []
++Win32_System_Search_Common = []
++Win32_System_SecurityCenter = []
++Win32_System_ServerBackup = []
++Win32_System_Services = []
++Win32_System_SettingsManagementInfrastructure = []
++Win32_System_SetupAndMigration = []
++Win32_System_Shutdown = []
++Win32_System_SideShow = []
++Win32_System_StationsAndDesktops = []
++Win32_System_SubsystemForLinux = []
++Win32_System_SystemInformation = []
++Win32_System_SystemServices = []
++Win32_System_TaskScheduler = []
++Win32_System_Threading = []
++Win32_System_Time = []
++Win32_System_TpmBaseServices = []
++Win32_System_TransactionServer = []
++Win32_System_UpdateAgent = []
++Win32_System_UpdateAssessment = []
++Win32_System_UserAccessLogging = []
++Win32_System_Variant = []
++Win32_System_VirtualDosMachines = []
++Win32_System_WinRT = []
++Win32_System_WinRT_AllJoyn = []
++Win32_System_WinRT_Composition = []
++Win32_System_WinRT_CoreInputView = []
++Win32_System_WinRT_Direct3D11 = []
++Win32_System_WinRT_Display = []
++Win32_System_WinRT_Graphics = []
++Win32_System_WinRT_Graphics_Capture = []
++Win32_System_WinRT_Graphics_Direct2D = []
++Win32_System_WinRT_Graphics_Imaging = []
++Win32_System_WinRT_Holographic = []
++Win32_System_WinRT_Isolation = []
++Win32_System_WinRT_ML = []
++Win32_System_WinRT_Media = []
++Win32_System_WinRT_Metadata = []
++Win32_System_WinRT_Pdf = []
++Win32_System_WinRT_Printing = []
++Win32_System_WinRT_Shell = []
++Win32_System_WinRT_Storage = []
++Win32_System_WindowsProgramming = []
++Win32_System_WindowsSync = []
++Win32_System_Wmi = []
++Win32_UI = []
++Win32_UI_Accessibility = []
++Win32_UI_Animation = []
++Win32_UI_ColorSystem = []
++Win32_UI_Controls = []
++Win32_UI_Controls_Dialogs = []
++Win32_UI_Controls_RichEdit = []
++Win32_UI_HiDpi = []
++Win32_UI_Input = []
++Win32_UI_Input_Ime = []
++Win32_UI_Input_Ink = []
++Win32_UI_Input_KeyboardAndMouse = []
++Win32_UI_Input_Pointer = []
++Win32_UI_Input_Radial = []
++Win32_UI_Input_Touch = []
++Win32_UI_Input_XboxController = []
++Win32_UI_InteractionContext = []
++Win32_UI_LegacyWindowsEnvironmentFeatures = []
++Win32_UI_Magnification = []
++Win32_UI_Notifications = []
++Win32_UI_Ribbon = []
++Win32_UI_Shell = []
++Win32_UI_Shell_Common = []
++Win32_UI_Shell_PropertiesSystem = []
++Win32_UI_TabletPC = []
++Win32_UI_TextServices = []
++Win32_UI_WindowsAndMessaging = []
++Win32_UI_Wpf = []
++Win32_Web = []
++Win32_Web_InternetExplorer = []
+ default = []
+ deprecated = []
+ docs = []
diff --git a/tests/configs/windows-0.54/debian/patches/series b/tests/configs/windows-0.54/debian/patches/series
new file mode 100644 (file)
index 0000000..20d1cc7
--- /dev/null
@@ -0,0 +1 @@
+remove-cycles.patch
diff --git a/tests/configs/windows-0.54/debian/rules b/tests/configs/windows-0.54/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/windows-0.54/debian/rules.debcargo.hint b/tests/configs/windows-0.54/debian/rules.debcargo.hint
new file mode 100755 (executable)
index 0000000..92c239b
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+
+override_dh_auto_test:
+       dh_auto_test -- test --all
diff --git a/tests/configs/windows-0.58/debian/changelog b/tests/configs/windows-0.58/debian/changelog
new file mode 100644 (file)
index 0000000..44e099c
--- /dev/null
@@ -0,0 +1,6 @@
+rust-windows-0.54 (0.54.0-1) UNRELEASED-FIXME-AUTOGENERATED-DEBCARGO; urgency=medium
+
+  * Team upload.
+  * Package windows 0.54.0 from crates.io using debcargo 2.6.1
+
+ -- Fabian Grünbichler <debian@fabian.gruenbichler.email>  Sat, 6 Jul 2024 21:13:52 +0200
diff --git a/tests/configs/windows-0.58/debian/debcargo.toml b/tests/configs/windows-0.58/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..96a9bd9
--- /dev/null
@@ -0,0 +1,7 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+test_is_broken = false
+[packages."lib+Win32_Foundation"]
+test_is_broken = false
diff --git a/tests/configs/windows-0.58/debian/patches/remove-cycles.patch b/tests/configs/windows-0.58/debian/patches/remove-cycles.patch
new file mode 100644 (file)
index 0000000..7e2d1f2
--- /dev/null
@@ -0,0 +1,1389 @@
+Index: rust-windows-0.58-0.58.0/Cargo.toml
+===================================================================
+--- rust-windows-0.58-0.58.0.orig/Cargo.toml
++++ rust-windows-0.58-0.58.0/Cargo.toml
+@@ -49,697 +49,697 @@ version = "0.58.0"
+ version = "0.52.6"
+ [features]
+-AI = ["Foundation"]
+-AI_MachineLearning = ["AI"]
+-ApplicationModel = ["Foundation"]
+-ApplicationModel_Activation = ["ApplicationModel"]
+-ApplicationModel_AppExtensions = ["ApplicationModel"]
+-ApplicationModel_AppService = ["ApplicationModel"]
+-ApplicationModel_Appointments = ["ApplicationModel"]
+-ApplicationModel_Appointments_AppointmentsProvider = ["ApplicationModel_Appointments"]
+-ApplicationModel_Appointments_DataProvider = ["ApplicationModel_Appointments"]
+-ApplicationModel_Background = ["ApplicationModel"]
+-ApplicationModel_Calls = ["ApplicationModel"]
+-ApplicationModel_Calls_Background = ["ApplicationModel_Calls"]
+-ApplicationModel_Calls_Provider = ["ApplicationModel_Calls"]
+-ApplicationModel_Chat = ["ApplicationModel"]
+-ApplicationModel_CommunicationBlocking = ["ApplicationModel"]
+-ApplicationModel_Contacts = ["ApplicationModel"]
+-ApplicationModel_Contacts_DataProvider = ["ApplicationModel_Contacts"]
+-ApplicationModel_Contacts_Provider = ["ApplicationModel_Contacts"]
+-ApplicationModel_ConversationalAgent = ["ApplicationModel"]
+-ApplicationModel_Core = ["ApplicationModel"]
+-ApplicationModel_DataTransfer = ["ApplicationModel"]
+-ApplicationModel_DataTransfer_DragDrop = ["ApplicationModel_DataTransfer"]
+-ApplicationModel_DataTransfer_DragDrop_Core = ["ApplicationModel_DataTransfer_DragDrop"]
+-ApplicationModel_DataTransfer_ShareTarget = ["ApplicationModel_DataTransfer"]
+-ApplicationModel_Email = ["ApplicationModel"]
+-ApplicationModel_Email_DataProvider = ["ApplicationModel_Email"]
+-ApplicationModel_ExtendedExecution = ["ApplicationModel"]
+-ApplicationModel_ExtendedExecution_Foreground = ["ApplicationModel_ExtendedExecution"]
+-ApplicationModel_Holographic = ["ApplicationModel"]
+-ApplicationModel_LockScreen = ["ApplicationModel"]
+-ApplicationModel_PackageExtensions = ["ApplicationModel"]
+-ApplicationModel_Payments = ["ApplicationModel"]
+-ApplicationModel_Payments_Provider = ["ApplicationModel_Payments"]
+-ApplicationModel_Preview = ["ApplicationModel"]
+-ApplicationModel_Preview_Holographic = ["ApplicationModel_Preview"]
+-ApplicationModel_Preview_InkWorkspace = ["ApplicationModel_Preview"]
+-ApplicationModel_Preview_Notes = ["ApplicationModel_Preview"]
+-ApplicationModel_Resources = ["ApplicationModel"]
+-ApplicationModel_Resources_Core = ["ApplicationModel_Resources"]
+-ApplicationModel_Resources_Management = ["ApplicationModel_Resources"]
+-ApplicationModel_Search = ["ApplicationModel"]
+-ApplicationModel_Search_Core = ["ApplicationModel_Search"]
+-ApplicationModel_UserActivities = ["ApplicationModel"]
+-ApplicationModel_UserActivities_Core = ["ApplicationModel_UserActivities"]
+-ApplicationModel_UserDataAccounts = ["ApplicationModel"]
+-ApplicationModel_UserDataAccounts_Provider = ["ApplicationModel_UserDataAccounts"]
+-ApplicationModel_UserDataAccounts_SystemAccess = ["ApplicationModel_UserDataAccounts"]
+-ApplicationModel_UserDataTasks = ["ApplicationModel"]
+-ApplicationModel_UserDataTasks_DataProvider = ["ApplicationModel_UserDataTasks"]
+-ApplicationModel_VoiceCommands = ["ApplicationModel"]
+-ApplicationModel_Wallet = ["ApplicationModel"]
+-ApplicationModel_Wallet_System = ["ApplicationModel_Wallet"]
+-Data = ["Foundation"]
+-Data_Html = ["Data"]
+-Data_Json = ["Data"]
+-Data_Pdf = ["Data"]
+-Data_Text = ["Data"]
+-Data_Xml = ["Data"]
+-Data_Xml_Dom = ["Data_Xml"]
+-Data_Xml_Xsl = ["Data_Xml"]
+-Devices = ["Foundation"]
+-Devices_Adc = ["Devices"]
+-Devices_Adc_Provider = ["Devices_Adc"]
+-Devices_Background = ["Devices"]
+-Devices_Bluetooth = ["Devices"]
+-Devices_Bluetooth_Advertisement = ["Devices_Bluetooth"]
+-Devices_Bluetooth_Background = ["Devices_Bluetooth"]
+-Devices_Bluetooth_GenericAttributeProfile = ["Devices_Bluetooth"]
+-Devices_Bluetooth_Rfcomm = ["Devices_Bluetooth"]
+-Devices_Custom = ["Devices"]
+-Devices_Display = ["Devices"]
+-Devices_Display_Core = ["Devices_Display"]
+-Devices_Enumeration = ["Devices"]
+-Devices_Enumeration_Pnp = ["Devices_Enumeration"]
+-Devices_Geolocation = ["Devices"]
+-Devices_Geolocation_Geofencing = ["Devices_Geolocation"]
+-Devices_Geolocation_Provider = ["Devices_Geolocation"]
+-Devices_Gpio = ["Devices"]
+-Devices_Gpio_Provider = ["Devices_Gpio"]
+-Devices_Haptics = ["Devices"]
+-Devices_HumanInterfaceDevice = ["Devices"]
+-Devices_I2c = ["Devices"]
+-Devices_I2c_Provider = ["Devices_I2c"]
+-Devices_Input = ["Devices"]
+-Devices_Input_Preview = ["Devices_Input"]
+-Devices_Lights = ["Devices"]
+-Devices_Lights_Effects = ["Devices_Lights"]
+-Devices_Midi = ["Devices"]
+-Devices_PointOfService = ["Devices"]
+-Devices_PointOfService_Provider = ["Devices_PointOfService"]
+-Devices_Portable = ["Devices"]
+-Devices_Power = ["Devices"]
+-Devices_Printers = ["Devices"]
+-Devices_Printers_Extensions = ["Devices_Printers"]
+-Devices_Pwm = ["Devices"]
+-Devices_Pwm_Provider = ["Devices_Pwm"]
+-Devices_Radios = ["Devices"]
+-Devices_Scanners = ["Devices"]
+-Devices_Sensors = ["Devices"]
+-Devices_Sensors_Custom = ["Devices_Sensors"]
+-Devices_SerialCommunication = ["Devices"]
+-Devices_SmartCards = ["Devices"]
+-Devices_Sms = ["Devices"]
+-Devices_Spi = ["Devices"]
+-Devices_Spi_Provider = ["Devices_Spi"]
+-Devices_Usb = ["Devices"]
+-Devices_WiFi = ["Devices"]
+-Devices_WiFiDirect = ["Devices"]
+-Devices_WiFiDirect_Services = ["Devices_WiFiDirect"]
+-Embedded = ["Foundation"]
+-Embedded_DeviceLockdown = ["Embedded"]
++AI = []
++AI_MachineLearning = []
++ApplicationModel = []
++ApplicationModel_Activation = []
++ApplicationModel_AppExtensions = []
++ApplicationModel_AppService = []
++ApplicationModel_Appointments = []
++ApplicationModel_Appointments_AppointmentsProvider = []
++ApplicationModel_Appointments_DataProvider = []
++ApplicationModel_Background = []
++ApplicationModel_Calls = []
++ApplicationModel_Calls_Background = []
++ApplicationModel_Calls_Provider = []
++ApplicationModel_Chat = []
++ApplicationModel_CommunicationBlocking = []
++ApplicationModel_Contacts = []
++ApplicationModel_Contacts_DataProvider = []
++ApplicationModel_Contacts_Provider = []
++ApplicationModel_ConversationalAgent = []
++ApplicationModel_Core = []
++ApplicationModel_DataTransfer = []
++ApplicationModel_DataTransfer_DragDrop = []
++ApplicationModel_DataTransfer_DragDrop_Core = []
++ApplicationModel_DataTransfer_ShareTarget = []
++ApplicationModel_Email = []
++ApplicationModel_Email_DataProvider = []
++ApplicationModel_ExtendedExecution = []
++ApplicationModel_ExtendedExecution_Foreground = []
++ApplicationModel_Holographic = []
++ApplicationModel_LockScreen = []
++ApplicationModel_PackageExtensions = []
++ApplicationModel_Payments = []
++ApplicationModel_Payments_Provider = []
++ApplicationModel_Preview = []
++ApplicationModel_Preview_Holographic = []
++ApplicationModel_Preview_InkWorkspace = []
++ApplicationModel_Preview_Notes = []
++ApplicationModel_Resources = []
++ApplicationModel_Resources_Core = []
++ApplicationModel_Resources_Management = []
++ApplicationModel_Search = []
++ApplicationModel_Search_Core = []
++ApplicationModel_UserActivities = []
++ApplicationModel_UserActivities_Core = []
++ApplicationModel_UserDataAccounts = []
++ApplicationModel_UserDataAccounts_Provider = []
++ApplicationModel_UserDataAccounts_SystemAccess = []
++ApplicationModel_UserDataTasks = []
++ApplicationModel_UserDataTasks_DataProvider = []
++ApplicationModel_VoiceCommands = []
++ApplicationModel_Wallet = []
++ApplicationModel_Wallet_System = []
++Data = []
++Data_Html = []
++Data_Json = []
++Data_Pdf = []
++Data_Text = []
++Data_Xml = []
++Data_Xml_Dom = []
++Data_Xml_Xsl = []
++Devices = []
++Devices_Adc = []
++Devices_Adc_Provider = []
++Devices_Background = []
++Devices_Bluetooth = []
++Devices_Bluetooth_Advertisement = []
++Devices_Bluetooth_Background = []
++Devices_Bluetooth_GenericAttributeProfile = []
++Devices_Bluetooth_Rfcomm = []
++Devices_Custom = []
++Devices_Display = []
++Devices_Display_Core = []
++Devices_Enumeration = []
++Devices_Enumeration_Pnp = []
++Devices_Geolocation = []
++Devices_Geolocation_Geofencing = []
++Devices_Geolocation_Provider = []
++Devices_Gpio = []
++Devices_Gpio_Provider = []
++Devices_Haptics = []
++Devices_HumanInterfaceDevice = []
++Devices_I2c = []
++Devices_I2c_Provider = []
++Devices_Input = []
++Devices_Input_Preview = []
++Devices_Lights = []
++Devices_Lights_Effects = []
++Devices_Midi = []
++Devices_PointOfService = []
++Devices_PointOfService_Provider = []
++Devices_Portable = []
++Devices_Power = []
++Devices_Printers = []
++Devices_Printers_Extensions = []
++Devices_Pwm = []
++Devices_Pwm_Provider = []
++Devices_Radios = []
++Devices_Scanners = []
++Devices_Sensors = []
++Devices_Sensors_Custom = []
++Devices_SerialCommunication = []
++Devices_SmartCards = []
++Devices_Sms = []
++Devices_Spi = []
++Devices_Spi_Provider = []
++Devices_Usb = []
++Devices_WiFi = []
++Devices_WiFiDirect = []
++Devices_WiFiDirect_Services = []
++Embedded = []
++Embedded_DeviceLockdown = []
+ Foundation = []
+-Foundation_Collections = ["Foundation"]
+-Foundation_Diagnostics = ["Foundation"]
+-Foundation_Metadata = ["Foundation"]
+-Foundation_Numerics = ["Foundation"]
+-Gaming = ["Foundation"]
+-Gaming_Input = ["Gaming"]
+-Gaming_Input_Custom = ["Gaming_Input"]
+-Gaming_Input_ForceFeedback = ["Gaming_Input"]
+-Gaming_Input_Preview = ["Gaming_Input"]
+-Gaming_Preview = ["Gaming"]
+-Gaming_Preview_GamesEnumeration = ["Gaming_Preview"]
+-Gaming_UI = ["Gaming"]
+-Gaming_XboxLive = ["Gaming"]
+-Gaming_XboxLive_Storage = ["Gaming_XboxLive"]
+-Globalization = ["Foundation"]
+-Globalization_Collation = ["Globalization"]
+-Globalization_DateTimeFormatting = ["Globalization"]
+-Globalization_Fonts = ["Globalization"]
+-Globalization_NumberFormatting = ["Globalization"]
+-Globalization_PhoneNumberFormatting = ["Globalization"]
+-Graphics = ["Foundation"]
+-Graphics_Capture = ["Graphics"]
+-Graphics_DirectX = ["Graphics"]
+-Graphics_DirectX_Direct3D11 = ["Graphics_DirectX"]
+-Graphics_Display = ["Graphics"]
+-Graphics_Display_Core = ["Graphics_Display"]
+-Graphics_Effects = ["Graphics"]
+-Graphics_Holographic = ["Graphics"]
+-Graphics_Imaging = ["Graphics"]
+-Graphics_Printing = ["Graphics"]
+-Graphics_Printing3D = ["Graphics"]
+-Graphics_Printing_OptionDetails = ["Graphics_Printing"]
+-Graphics_Printing_PrintSupport = ["Graphics_Printing"]
+-Graphics_Printing_PrintTicket = ["Graphics_Printing"]
+-Graphics_Printing_Workflow = ["Graphics_Printing"]
+-Management = ["Foundation"]
+-Management_Core = ["Management"]
+-Management_Deployment = ["Management"]
+-Management_Deployment_Preview = ["Management_Deployment"]
+-Management_Policies = ["Management"]
+-Management_Setup = ["Management"]
+-Management_Update = ["Management"]
+-Management_Workplace = ["Management"]
+-Media = ["Foundation"]
+-Media_AppBroadcasting = ["Media"]
+-Media_AppRecording = ["Media"]
+-Media_Audio = ["Media"]
+-Media_Capture = ["Media"]
+-Media_Capture_Core = ["Media_Capture"]
+-Media_Capture_Frames = ["Media_Capture"]
+-Media_Casting = ["Media"]
+-Media_ClosedCaptioning = ["Media"]
+-Media_ContentRestrictions = ["Media"]
+-Media_Control = ["Media"]
+-Media_Core = ["Media"]
+-Media_Core_Preview = ["Media_Core"]
+-Media_Devices = ["Media"]
+-Media_Devices_Core = ["Media_Devices"]
+-Media_DialProtocol = ["Media"]
+-Media_Editing = ["Media"]
+-Media_Effects = ["Media"]
+-Media_FaceAnalysis = ["Media"]
+-Media_Import = ["Media"]
+-Media_MediaProperties = ["Media"]
+-Media_Miracast = ["Media"]
+-Media_Ocr = ["Media"]
+-Media_PlayTo = ["Media"]
+-Media_Playback = ["Media"]
+-Media_Playlists = ["Media"]
+-Media_Protection = ["Media"]
+-Media_Protection_PlayReady = ["Media_Protection"]
+-Media_Render = ["Media"]
+-Media_SpeechRecognition = ["Media"]
+-Media_SpeechSynthesis = ["Media"]
+-Media_Streaming = ["Media"]
+-Media_Streaming_Adaptive = ["Media_Streaming"]
+-Media_Transcoding = ["Media"]
+-Networking = ["Foundation"]
+-Networking_BackgroundTransfer = ["Networking"]
+-Networking_Connectivity = ["Networking"]
+-Networking_NetworkOperators = ["Networking"]
+-Networking_Proximity = ["Networking"]
+-Networking_PushNotifications = ["Networking"]
+-Networking_ServiceDiscovery = ["Networking"]
+-Networking_ServiceDiscovery_Dnssd = ["Networking_ServiceDiscovery"]
+-Networking_Sockets = ["Networking"]
+-Networking_Vpn = ["Networking"]
+-Networking_XboxLive = ["Networking"]
+-Perception = ["Foundation"]
+-Perception_Automation = ["Perception"]
+-Perception_Automation_Core = ["Perception_Automation"]
+-Perception_People = ["Perception"]
+-Perception_Spatial = ["Perception"]
+-Perception_Spatial_Preview = ["Perception_Spatial"]
+-Perception_Spatial_Surfaces = ["Perception_Spatial"]
+-Phone = ["Foundation"]
+-Phone_ApplicationModel = ["Phone"]
+-Phone_Devices = ["Phone"]
+-Phone_Devices_Notification = ["Phone_Devices"]
+-Phone_Devices_Power = ["Phone_Devices"]
+-Phone_Management = ["Phone"]
+-Phone_Management_Deployment = ["Phone_Management"]
+-Phone_Media = ["Phone"]
+-Phone_Media_Devices = ["Phone_Media"]
+-Phone_Notification = ["Phone"]
+-Phone_Notification_Management = ["Phone_Notification"]
+-Phone_PersonalInformation = ["Phone"]
+-Phone_PersonalInformation_Provisioning = ["Phone_PersonalInformation"]
+-Phone_Speech = ["Phone"]
+-Phone_Speech_Recognition = ["Phone_Speech"]
+-Phone_StartScreen = ["Phone"]
+-Phone_System = ["Phone"]
+-Phone_System_Power = ["Phone_System"]
+-Phone_System_Profile = ["Phone_System"]
+-Phone_System_UserProfile = ["Phone_System"]
+-Phone_System_UserProfile_GameServices = ["Phone_System_UserProfile"]
+-Phone_System_UserProfile_GameServices_Core = ["Phone_System_UserProfile_GameServices"]
+-Phone_UI = ["Phone"]
+-Phone_UI_Input = ["Phone_UI"]
+-Security = ["Foundation"]
+-Security_Authentication = ["Security"]
+-Security_Authentication_Identity = ["Security_Authentication"]
+-Security_Authentication_Identity_Core = ["Security_Authentication_Identity"]
+-Security_Authentication_OnlineId = ["Security_Authentication"]
+-Security_Authentication_Web = ["Security_Authentication"]
+-Security_Authentication_Web_Core = ["Security_Authentication_Web"]
+-Security_Authentication_Web_Provider = ["Security_Authentication_Web"]
+-Security_Authorization = ["Security"]
+-Security_Authorization_AppCapabilityAccess = ["Security_Authorization"]
+-Security_Credentials = ["Security"]
+-Security_Credentials_UI = ["Security_Credentials"]
+-Security_Cryptography = ["Security"]
+-Security_Cryptography_Certificates = ["Security_Cryptography"]
+-Security_Cryptography_Core = ["Security_Cryptography"]
+-Security_Cryptography_DataProtection = ["Security_Cryptography"]
+-Security_DataProtection = ["Security"]
+-Security_EnterpriseData = ["Security"]
+-Security_ExchangeActiveSyncProvisioning = ["Security"]
+-Security_Isolation = ["Security"]
+-Services = ["Foundation"]
+-Services_Maps = ["Services"]
+-Services_Maps_Guidance = ["Services_Maps"]
+-Services_Maps_LocalSearch = ["Services_Maps"]
+-Services_Maps_OfflineMaps = ["Services_Maps"]
+-Services_Store = ["Services"]
+-Services_TargetedContent = ["Services"]
+-Storage = ["Foundation"]
+-Storage_AccessCache = ["Storage"]
+-Storage_BulkAccess = ["Storage"]
+-Storage_Compression = ["Storage"]
+-Storage_FileProperties = ["Storage"]
+-Storage_Pickers = ["Storage"]
+-Storage_Pickers_Provider = ["Storage_Pickers"]
+-Storage_Provider = ["Storage"]
+-Storage_Search = ["Storage"]
+-Storage_Streams = ["Storage"]
+-System = ["Foundation"]
+-System_Diagnostics = ["System"]
+-System_Diagnostics_DevicePortal = ["System_Diagnostics"]
+-System_Diagnostics_Telemetry = ["System_Diagnostics"]
+-System_Diagnostics_TraceReporting = ["System_Diagnostics"]
+-System_Display = ["System"]
+-System_Implementation = ["System"]
+-System_Implementation_FileExplorer = ["System_Implementation"]
+-System_Inventory = ["System"]
+-System_Power = ["System"]
+-System_Profile = ["System"]
+-System_Profile_SystemManufacturers = ["System_Profile"]
+-System_RemoteDesktop = ["System"]
+-System_RemoteDesktop_Input = ["System_RemoteDesktop"]
+-System_RemoteDesktop_Provider = ["System_RemoteDesktop"]
+-System_RemoteSystems = ["System"]
+-System_Threading = ["System"]
+-System_Threading_Core = ["System_Threading"]
+-System_Update = ["System"]
+-System_UserProfile = ["System"]
+-UI = ["Foundation"]
+-UI_Accessibility = ["UI"]
+-UI_ApplicationSettings = ["UI"]
+-UI_Composition = ["UI"]
+-UI_Composition_Core = ["UI_Composition"]
+-UI_Composition_Desktop = ["UI_Composition"]
+-UI_Composition_Diagnostics = ["UI_Composition"]
+-UI_Composition_Effects = ["UI_Composition"]
+-UI_Composition_Interactions = ["UI_Composition"]
+-UI_Composition_Scenes = ["UI_Composition"]
+-UI_Core = ["UI"]
+-UI_Core_AnimationMetrics = ["UI_Core"]
+-UI_Core_Preview = ["UI_Core"]
+-UI_Input = ["UI"]
+-UI_Input_Core = ["UI_Input"]
+-UI_Input_Inking = ["UI_Input"]
+-UI_Input_Inking_Analysis = ["UI_Input_Inking"]
+-UI_Input_Inking_Core = ["UI_Input_Inking"]
+-UI_Input_Inking_Preview = ["UI_Input_Inking"]
+-UI_Input_Preview = ["UI_Input"]
+-UI_Input_Preview_Injection = ["UI_Input_Preview"]
+-UI_Input_Spatial = ["UI_Input"]
+-UI_Notifications = ["UI"]
+-UI_Notifications_Management = ["UI_Notifications"]
+-UI_Notifications_Preview = ["UI_Notifications"]
+-UI_Popups = ["UI"]
+-UI_Shell = ["UI"]
+-UI_StartScreen = ["UI"]
+-UI_Text = ["UI"]
+-UI_Text_Core = ["UI_Text"]
+-UI_UIAutomation = ["UI"]
+-UI_UIAutomation_Core = ["UI_UIAutomation"]
+-UI_ViewManagement = ["UI"]
+-UI_ViewManagement_Core = ["UI_ViewManagement"]
+-UI_WebUI = ["UI"]
+-UI_WebUI_Core = ["UI_WebUI"]
+-UI_WindowManagement = ["UI"]
+-UI_WindowManagement_Preview = ["UI_WindowManagement"]
+-Wdk = ["Win32_Foundation"]
+-Wdk_Devices = ["Wdk"]
+-Wdk_Devices_Bluetooth = ["Wdk_Devices"]
+-Wdk_Devices_HumanInterfaceDevice = ["Wdk_Devices"]
+-Wdk_Foundation = ["Wdk"]
+-Wdk_Graphics = ["Wdk"]
+-Wdk_Graphics_Direct3D = ["Wdk_Graphics"]
+-Wdk_NetworkManagement = ["Wdk"]
+-Wdk_NetworkManagement_Ndis = ["Wdk_NetworkManagement"]
+-Wdk_NetworkManagement_WindowsFilteringPlatform = ["Wdk_NetworkManagement"]
+-Wdk_Storage = ["Wdk"]
+-Wdk_Storage_FileSystem = ["Wdk_Storage"]
+-Wdk_Storage_FileSystem_Minifilters = ["Wdk_Storage_FileSystem"]
+-Wdk_System = ["Wdk"]
+-Wdk_System_IO = ["Wdk_System"]
+-Wdk_System_Memory = ["Wdk_System"]
+-Wdk_System_OfflineRegistry = ["Wdk_System"]
+-Wdk_System_Registry = ["Wdk_System"]
+-Wdk_System_SystemInformation = ["Wdk_System"]
+-Wdk_System_SystemServices = ["Wdk_System"]
+-Wdk_System_Threading = ["Wdk_System"]
+-Web = ["Foundation"]
+-Web_AtomPub = ["Web"]
+-Web_Http = ["Web"]
+-Web_Http_Diagnostics = ["Web_Http"]
+-Web_Http_Filters = ["Web_Http"]
+-Web_Http_Headers = ["Web_Http"]
+-Web_Syndication = ["Web"]
+-Web_UI = ["Web"]
+-Web_UI_Interop = ["Web_UI"]
+-Win32 = ["Win32_Foundation"]
+-Win32_AI = ["Win32"]
+-Win32_AI_MachineLearning = ["Win32_AI"]
+-Win32_AI_MachineLearning_DirectML = ["Win32_AI_MachineLearning"]
+-Win32_AI_MachineLearning_WinML = ["Win32_AI_MachineLearning"]
+-Win32_Data = ["Win32"]
+-Win32_Data_HtmlHelp = ["Win32_Data"]
+-Win32_Data_RightsManagement = ["Win32_Data"]
+-Win32_Data_Xml = ["Win32_Data"]
+-Win32_Data_Xml_MsXml = ["Win32_Data_Xml"]
+-Win32_Data_Xml_XmlLite = ["Win32_Data_Xml"]
+-Win32_Devices = ["Win32"]
+-Win32_Devices_AllJoyn = ["Win32_Devices"]
+-Win32_Devices_BiometricFramework = ["Win32_Devices"]
+-Win32_Devices_Bluetooth = ["Win32_Devices"]
+-Win32_Devices_Communication = ["Win32_Devices"]
+-Win32_Devices_DeviceAccess = ["Win32_Devices"]
+-Win32_Devices_DeviceAndDriverInstallation = ["Win32_Devices"]
+-Win32_Devices_DeviceQuery = ["Win32_Devices"]
+-Win32_Devices_Display = ["Win32_Devices"]
+-Win32_Devices_Enumeration = ["Win32_Devices"]
+-Win32_Devices_Enumeration_Pnp = ["Win32_Devices_Enumeration"]
+-Win32_Devices_Fax = ["Win32_Devices"]
+-Win32_Devices_FunctionDiscovery = ["Win32_Devices"]
+-Win32_Devices_Geolocation = ["Win32_Devices"]
+-Win32_Devices_HumanInterfaceDevice = ["Win32_Devices"]
+-Win32_Devices_ImageAcquisition = ["Win32_Devices"]
+-Win32_Devices_PortableDevices = ["Win32_Devices"]
+-Win32_Devices_Properties = ["Win32_Devices"]
+-Win32_Devices_Pwm = ["Win32_Devices"]
+-Win32_Devices_Sensors = ["Win32_Devices"]
+-Win32_Devices_SerialCommunication = ["Win32_Devices"]
+-Win32_Devices_Tapi = ["Win32_Devices"]
+-Win32_Devices_Usb = ["Win32_Devices"]
+-Win32_Devices_WebServicesOnDevices = ["Win32_Devices"]
+-Win32_Foundation = ["Win32"]
+-Win32_Gaming = ["Win32"]
+-Win32_Globalization = ["Win32"]
+-Win32_Graphics = ["Win32"]
+-Win32_Graphics_CompositionSwapchain = ["Win32_Graphics"]
+-Win32_Graphics_DXCore = ["Win32_Graphics"]
+-Win32_Graphics_Direct2D = ["Win32_Graphics"]
+-Win32_Graphics_Direct2D_Common = ["Win32_Graphics_Direct2D"]
+-Win32_Graphics_Direct3D = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D10 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D11 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D11on12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D9 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D9on12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D_Dxc = ["Win32_Graphics_Direct3D"]
+-Win32_Graphics_Direct3D_Fxc = ["Win32_Graphics_Direct3D"]
+-Win32_Graphics_DirectComposition = ["Win32_Graphics"]
+-Win32_Graphics_DirectDraw = ["Win32_Graphics"]
+-Win32_Graphics_DirectManipulation = ["Win32_Graphics"]
+-Win32_Graphics_DirectWrite = ["Win32_Graphics"]
+-Win32_Graphics_Dwm = ["Win32_Graphics"]
+-Win32_Graphics_Dxgi = ["Win32_Graphics"]
+-Win32_Graphics_Dxgi_Common = ["Win32_Graphics_Dxgi"]
+-Win32_Graphics_Gdi = ["Win32_Graphics"]
+-Win32_Graphics_GdiPlus = ["Win32_Graphics"]
+-Win32_Graphics_Hlsl = ["Win32_Graphics"]
+-Win32_Graphics_Imaging = ["Win32_Graphics"]
+-Win32_Graphics_Imaging_D2D = ["Win32_Graphics_Imaging"]
+-Win32_Graphics_OpenGL = ["Win32_Graphics"]
+-Win32_Graphics_Printing = ["Win32_Graphics"]
+-Win32_Graphics_Printing_PrintTicket = ["Win32_Graphics_Printing"]
+-Win32_Management = ["Win32"]
+-Win32_Management_MobileDeviceManagementRegistration = ["Win32_Management"]
+-Win32_Media = ["Win32"]
+-Win32_Media_Audio = ["Win32_Media"]
+-Win32_Media_Audio_Apo = ["Win32_Media_Audio"]
+-Win32_Media_Audio_DirectMusic = ["Win32_Media_Audio"]
+-Win32_Media_Audio_DirectSound = ["Win32_Media_Audio"]
+-Win32_Media_Audio_Endpoints = ["Win32_Media_Audio"]
+-Win32_Media_Audio_XAudio2 = ["Win32_Media_Audio"]
+-Win32_Media_DeviceManager = ["Win32_Media"]
+-Win32_Media_DirectShow = ["Win32_Media"]
+-Win32_Media_DirectShow_Tv = ["Win32_Media_DirectShow"]
+-Win32_Media_DirectShow_Xml = ["Win32_Media_DirectShow"]
+-Win32_Media_DxMediaObjects = ["Win32_Media"]
+-Win32_Media_KernelStreaming = ["Win32_Media"]
+-Win32_Media_LibrarySharingServices = ["Win32_Media"]
+-Win32_Media_MediaFoundation = ["Win32_Media"]
+-Win32_Media_MediaPlayer = ["Win32_Media"]
+-Win32_Media_Multimedia = ["Win32_Media"]
+-Win32_Media_PictureAcquisition = ["Win32_Media"]
+-Win32_Media_Speech = ["Win32_Media"]
+-Win32_Media_Streaming = ["Win32_Media"]
+-Win32_Media_WindowsMediaFormat = ["Win32_Media"]
+-Win32_NetworkManagement = ["Win32"]
+-Win32_NetworkManagement_Dhcp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Dns = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_InternetConnectionWizard = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_IpHelper = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_MobileBroadband = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Multicast = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Ndis = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetBios = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetManagement = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetShell = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetworkDiagnosticsFramework = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetworkPolicyServer = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_P2P = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_QoS = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Rras = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Snmp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WNet = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WebDav = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WiFi = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsConnectNow = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsConnectionManager = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFilteringPlatform = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFirewall = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsNetworkVirtualization = ["Win32_NetworkManagement"]
+-Win32_Networking = ["Win32"]
+-Win32_Networking_ActiveDirectory = ["Win32_Networking"]
+-Win32_Networking_BackgroundIntelligentTransferService = ["Win32_Networking"]
+-Win32_Networking_Clustering = ["Win32_Networking"]
+-Win32_Networking_HttpServer = ["Win32_Networking"]
+-Win32_Networking_Ldap = ["Win32_Networking"]
+-Win32_Networking_NetworkListManager = ["Win32_Networking"]
+-Win32_Networking_RemoteDifferentialCompression = ["Win32_Networking"]
+-Win32_Networking_WebSocket = ["Win32_Networking"]
+-Win32_Networking_WinHttp = ["Win32_Networking"]
+-Win32_Networking_WinInet = ["Win32_Networking"]
+-Win32_Networking_WinSock = ["Win32_Networking"]
+-Win32_Networking_WindowsWebServices = ["Win32_Networking"]
+-Win32_Security = ["Win32"]
+-Win32_Security_AppLocker = ["Win32_Security"]
+-Win32_Security_Authentication = ["Win32_Security"]
+-Win32_Security_Authentication_Identity = ["Win32_Security_Authentication"]
+-Win32_Security_Authentication_Identity_Provider = ["Win32_Security_Authentication_Identity"]
+-Win32_Security_Authorization = ["Win32_Security"]
+-Win32_Security_Authorization_UI = ["Win32_Security_Authorization"]
+-Win32_Security_ConfigurationSnapin = ["Win32_Security"]
+-Win32_Security_Credentials = ["Win32_Security"]
+-Win32_Security_Cryptography = ["Win32_Security"]
+-Win32_Security_Cryptography_Catalog = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Certificates = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Sip = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_UI = ["Win32_Security_Cryptography"]
+-Win32_Security_DiagnosticDataQuery = ["Win32_Security"]
+-Win32_Security_DirectoryServices = ["Win32_Security"]
+-Win32_Security_EnterpriseData = ["Win32_Security"]
+-Win32_Security_ExtensibleAuthenticationProtocol = ["Win32_Security"]
+-Win32_Security_Isolation = ["Win32_Security"]
+-Win32_Security_LicenseProtection = ["Win32_Security"]
+-Win32_Security_NetworkAccessProtection = ["Win32_Security"]
+-Win32_Security_Tpm = ["Win32_Security"]
+-Win32_Security_WinTrust = ["Win32_Security"]
+-Win32_Security_WinWlx = ["Win32_Security"]
+-Win32_Storage = ["Win32"]
+-Win32_Storage_Cabinets = ["Win32_Storage"]
+-Win32_Storage_CloudFilters = ["Win32_Storage"]
+-Win32_Storage_Compression = ["Win32_Storage"]
+-Win32_Storage_DataDeduplication = ["Win32_Storage"]
+-Win32_Storage_DistributedFileSystem = ["Win32_Storage"]
+-Win32_Storage_EnhancedStorage = ["Win32_Storage"]
+-Win32_Storage_FileHistory = ["Win32_Storage"]
+-Win32_Storage_FileServerResourceManager = ["Win32_Storage"]
+-Win32_Storage_FileSystem = ["Win32_Storage"]
+-Win32_Storage_Imapi = ["Win32_Storage"]
+-Win32_Storage_IndexServer = ["Win32_Storage"]
+-Win32_Storage_InstallableFileSystems = ["Win32_Storage"]
+-Win32_Storage_IscsiDisc = ["Win32_Storage"]
+-Win32_Storage_Jet = ["Win32_Storage"]
+-Win32_Storage_Nvme = ["Win32_Storage"]
+-Win32_Storage_OfflineFiles = ["Win32_Storage"]
+-Win32_Storage_OperationRecorder = ["Win32_Storage"]
+-Win32_Storage_Packaging = ["Win32_Storage"]
+-Win32_Storage_Packaging_Appx = ["Win32_Storage_Packaging"]
+-Win32_Storage_Packaging_Opc = ["Win32_Storage_Packaging"]
+-Win32_Storage_ProjectedFileSystem = ["Win32_Storage"]
+-Win32_Storage_StructuredStorage = ["Win32_Storage"]
+-Win32_Storage_Vhd = ["Win32_Storage"]
+-Win32_Storage_VirtualDiskService = ["Win32_Storage"]
+-Win32_Storage_Vss = ["Win32_Storage"]
+-Win32_Storage_Xps = ["Win32_Storage"]
+-Win32_Storage_Xps_Printing = ["Win32_Storage_Xps"]
+-Win32_System = ["Win32"]
+-Win32_System_AddressBook = ["Win32_System"]
+-Win32_System_Antimalware = ["Win32_System"]
+-Win32_System_ApplicationInstallationAndServicing = ["Win32_System"]
+-Win32_System_ApplicationVerifier = ["Win32_System"]
+-Win32_System_AssessmentTool = ["Win32_System"]
+-Win32_System_ClrHosting = ["Win32_System"]
+-Win32_System_Com = ["Win32_System"]
+-Win32_System_Com_CallObj = ["Win32_System_Com"]
+-Win32_System_Com_ChannelCredentials = ["Win32_System_Com"]
+-Win32_System_Com_Events = ["Win32_System_Com"]
+-Win32_System_Com_Marshal = ["Win32_System_Com"]
+-Win32_System_Com_StructuredStorage = ["Win32_System_Com"]
+-Win32_System_Com_UI = ["Win32_System_Com"]
+-Win32_System_Com_Urlmon = ["Win32_System_Com"]
+-Win32_System_ComponentServices = ["Win32_System"]
+-Win32_System_Console = ["Win32_System"]
+-Win32_System_Contacts = ["Win32_System"]
+-Win32_System_CorrelationVector = ["Win32_System"]
+-Win32_System_DataExchange = ["Win32_System"]
+-Win32_System_DeploymentServices = ["Win32_System"]
+-Win32_System_DesktopSharing = ["Win32_System"]
+-Win32_System_DeveloperLicensing = ["Win32_System"]
+-Win32_System_Diagnostics = ["Win32_System"]
+-Win32_System_Diagnostics_Ceip = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ClrProfiling = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug_ActiveScript = ["Win32_System_Diagnostics_Debug"]
+-Win32_System_Diagnostics_Debug_Extensions = ["Win32_System_Diagnostics_Debug"]
+-Win32_System_Diagnostics_Etw = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ProcessSnapshotting = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ToolHelp = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_TraceLogging = ["Win32_System_Diagnostics"]
+-Win32_System_DistributedTransactionCoordinator = ["Win32_System"]
+-Win32_System_Environment = ["Win32_System"]
+-Win32_System_ErrorReporting = ["Win32_System"]
+-Win32_System_EventCollector = ["Win32_System"]
+-Win32_System_EventLog = ["Win32_System"]
+-Win32_System_EventNotificationService = ["Win32_System"]
+-Win32_System_GroupPolicy = ["Win32_System"]
+-Win32_System_HostCompute = ["Win32_System"]
+-Win32_System_HostComputeNetwork = ["Win32_System"]
+-Win32_System_HostComputeSystem = ["Win32_System"]
+-Win32_System_Hypervisor = ["Win32_System"]
+-Win32_System_IO = ["Win32_System"]
+-Win32_System_Iis = ["Win32_System"]
+-Win32_System_Ioctl = ["Win32_System"]
+-Win32_System_JobObjects = ["Win32_System"]
+-Win32_System_Js = ["Win32_System"]
+-Win32_System_Kernel = ["Win32_System"]
+-Win32_System_LibraryLoader = ["Win32_System"]
+-Win32_System_Mailslots = ["Win32_System"]
+-Win32_System_Mapi = ["Win32_System"]
+-Win32_System_Memory = ["Win32_System"]
+-Win32_System_Memory_NonVolatile = ["Win32_System_Memory"]
+-Win32_System_MessageQueuing = ["Win32_System"]
+-Win32_System_MixedReality = ["Win32_System"]
+-Win32_System_Mmc = ["Win32_System"]
+-Win32_System_Ole = ["Win32_System"]
+-Win32_System_ParentalControls = ["Win32_System"]
+-Win32_System_PasswordManagement = ["Win32_System"]
+-Win32_System_Performance = ["Win32_System"]
+-Win32_System_Performance_HardwareCounterProfiling = ["Win32_System_Performance"]
+-Win32_System_Pipes = ["Win32_System"]
+-Win32_System_Power = ["Win32_System"]
+-Win32_System_ProcessStatus = ["Win32_System"]
+-Win32_System_RealTimeCommunications = ["Win32_System"]
+-Win32_System_Recovery = ["Win32_System"]
+-Win32_System_Registry = ["Win32_System"]
+-Win32_System_RemoteAssistance = ["Win32_System"]
+-Win32_System_RemoteDesktop = ["Win32_System"]
+-Win32_System_RemoteManagement = ["Win32_System"]
+-Win32_System_RestartManager = ["Win32_System"]
+-Win32_System_Restore = ["Win32_System"]
+-Win32_System_Rpc = ["Win32_System"]
+-Win32_System_Search = ["Win32_System"]
+-Win32_System_Search_Common = ["Win32_System_Search"]
+-Win32_System_SecurityCenter = ["Win32_System"]
+-Win32_System_ServerBackup = ["Win32_System"]
+-Win32_System_Services = ["Win32_System"]
+-Win32_System_SettingsManagementInfrastructure = ["Win32_System"]
+-Win32_System_SetupAndMigration = ["Win32_System"]
+-Win32_System_Shutdown = ["Win32_System"]
+-Win32_System_SideShow = ["Win32_System"]
+-Win32_System_StationsAndDesktops = ["Win32_System"]
+-Win32_System_SubsystemForLinux = ["Win32_System"]
+-Win32_System_SystemInformation = ["Win32_System"]
+-Win32_System_SystemServices = ["Win32_System"]
+-Win32_System_TaskScheduler = ["Win32_System"]
+-Win32_System_Threading = ["Win32_System"]
+-Win32_System_Time = ["Win32_System"]
+-Win32_System_TpmBaseServices = ["Win32_System"]
+-Win32_System_TransactionServer = ["Win32_System"]
+-Win32_System_UpdateAgent = ["Win32_System"]
+-Win32_System_UpdateAssessment = ["Win32_System"]
+-Win32_System_UserAccessLogging = ["Win32_System"]
+-Win32_System_Variant = ["Win32_System"]
+-Win32_System_VirtualDosMachines = ["Win32_System"]
+-Win32_System_WinRT = ["Win32_System"]
+-Win32_System_WinRT_AllJoyn = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Composition = ["Win32_System_WinRT"]
+-Win32_System_WinRT_CoreInputView = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Direct3D11 = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Display = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Graphics = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Graphics_Capture = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Graphics_Direct2D = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Graphics_Imaging = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Holographic = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Isolation = ["Win32_System_WinRT"]
+-Win32_System_WinRT_ML = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Media = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Metadata = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Pdf = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Printing = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Shell = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Storage = ["Win32_System_WinRT"]
+-Win32_System_WindowsProgramming = ["Win32_System"]
+-Win32_System_WindowsSync = ["Win32_System"]
+-Win32_System_Wmi = ["Win32_System"]
+-Win32_UI = ["Win32"]
+-Win32_UI_Accessibility = ["Win32_UI"]
+-Win32_UI_Animation = ["Win32_UI"]
+-Win32_UI_ColorSystem = ["Win32_UI"]
+-Win32_UI_Controls = ["Win32_UI"]
+-Win32_UI_Controls_Dialogs = ["Win32_UI_Controls"]
+-Win32_UI_Controls_RichEdit = ["Win32_UI_Controls"]
+-Win32_UI_HiDpi = ["Win32_UI"]
+-Win32_UI_Input = ["Win32_UI"]
+-Win32_UI_Input_Ime = ["Win32_UI_Input"]
+-Win32_UI_Input_Ink = ["Win32_UI_Input"]
+-Win32_UI_Input_KeyboardAndMouse = ["Win32_UI_Input"]
+-Win32_UI_Input_Pointer = ["Win32_UI_Input"]
+-Win32_UI_Input_Radial = ["Win32_UI_Input"]
+-Win32_UI_Input_Touch = ["Win32_UI_Input"]
+-Win32_UI_Input_XboxController = ["Win32_UI_Input"]
+-Win32_UI_InteractionContext = ["Win32_UI"]
+-Win32_UI_LegacyWindowsEnvironmentFeatures = ["Win32_UI"]
+-Win32_UI_Magnification = ["Win32_UI"]
+-Win32_UI_Notifications = ["Win32_UI"]
+-Win32_UI_Ribbon = ["Win32_UI"]
+-Win32_UI_Shell = ["Win32_UI"]
+-Win32_UI_Shell_Common = ["Win32_UI_Shell"]
+-Win32_UI_Shell_PropertiesSystem = ["Win32_UI_Shell"]
+-Win32_UI_TabletPC = ["Win32_UI"]
+-Win32_UI_TextServices = ["Win32_UI"]
+-Win32_UI_WindowsAndMessaging = ["Win32_UI"]
+-Win32_UI_Wpf = ["Win32_UI"]
+-Win32_Web = ["Win32"]
+-Win32_Web_InternetExplorer = ["Win32_Web"]
+-default = ["std"]
++Foundation_Collections = []
++Foundation_Diagnostics = []
++Foundation_Metadata = []
++Foundation_Numerics = []
++Gaming = []
++Gaming_Input = []
++Gaming_Input_Custom = []
++Gaming_Input_ForceFeedback = []
++Gaming_Input_Preview = []
++Gaming_Preview = []
++Gaming_Preview_GamesEnumeration = []
++Gaming_UI = []
++Gaming_XboxLive = []
++Gaming_XboxLive_Storage = []
++Globalization = []
++Globalization_Collation = []
++Globalization_DateTimeFormatting = []
++Globalization_Fonts = []
++Globalization_NumberFormatting = []
++Globalization_PhoneNumberFormatting = []
++Graphics = []
++Graphics_Capture = []
++Graphics_DirectX = []
++Graphics_DirectX_Direct3D11 = []
++Graphics_Display = []
++Graphics_Display_Core = []
++Graphics_Effects = []
++Graphics_Holographic = []
++Graphics_Imaging = []
++Graphics_Printing = []
++Graphics_Printing3D = []
++Graphics_Printing_OptionDetails = []
++Graphics_Printing_PrintSupport = []
++Graphics_Printing_PrintTicket = []
++Graphics_Printing_Workflow = []
++Management = []
++Management_Core = []
++Management_Deployment = []
++Management_Deployment_Preview = []
++Management_Policies = []
++Management_Setup = []
++Management_Update = []
++Management_Workplace = []
++Media = []
++Media_AppBroadcasting = []
++Media_AppRecording = []
++Media_Audio = []
++Media_Capture = []
++Media_Capture_Core = []
++Media_Capture_Frames = []
++Media_Casting = []
++Media_ClosedCaptioning = []
++Media_ContentRestrictions = []
++Media_Control = []
++Media_Core = []
++Media_Core_Preview = []
++Media_Devices = []
++Media_Devices_Core = []
++Media_DialProtocol = []
++Media_Editing = []
++Media_Effects = []
++Media_FaceAnalysis = []
++Media_Import = []
++Media_MediaProperties = []
++Media_Miracast = []
++Media_Ocr = []
++Media_PlayTo = []
++Media_Playback = []
++Media_Playlists = []
++Media_Protection = []
++Media_Protection_PlayReady = []
++Media_Render = []
++Media_SpeechRecognition = []
++Media_SpeechSynthesis = []
++Media_Streaming = []
++Media_Streaming_Adaptive = []
++Media_Transcoding = []
++Networking = []
++Networking_BackgroundTransfer = []
++Networking_Connectivity = []
++Networking_NetworkOperators = []
++Networking_Proximity = []
++Networking_PushNotifications = []
++Networking_ServiceDiscovery = []
++Networking_ServiceDiscovery_Dnssd = []
++Networking_Sockets = []
++Networking_Vpn = []
++Networking_XboxLive = []
++Perception = []
++Perception_Automation = []
++Perception_Automation_Core = []
++Perception_People = []
++Perception_Spatial = []
++Perception_Spatial_Preview = []
++Perception_Spatial_Surfaces = []
++Phone = []
++Phone_ApplicationModel = []
++Phone_Devices = []
++Phone_Devices_Notification = []
++Phone_Devices_Power = []
++Phone_Management = []
++Phone_Management_Deployment = []
++Phone_Media = []
++Phone_Media_Devices = []
++Phone_Notification = []
++Phone_Notification_Management = []
++Phone_PersonalInformation = []
++Phone_PersonalInformation_Provisioning = []
++Phone_Speech = []
++Phone_Speech_Recognition = []
++Phone_StartScreen = []
++Phone_System = []
++Phone_System_Power = []
++Phone_System_Profile = []
++Phone_System_UserProfile = []
++Phone_System_UserProfile_GameServices = []
++Phone_System_UserProfile_GameServices_Core = []
++Phone_UI = []
++Phone_UI_Input = []
++Security = []
++Security_Authentication = []
++Security_Authentication_Identity = []
++Security_Authentication_Identity_Core = []
++Security_Authentication_OnlineId = []
++Security_Authentication_Web = []
++Security_Authentication_Web_Core = []
++Security_Authentication_Web_Provider = []
++Security_Authorization = []
++Security_Authorization_AppCapabilityAccess = []
++Security_Credentials = []
++Security_Credentials_UI = []
++Security_Cryptography = []
++Security_Cryptography_Certificates = []
++Security_Cryptography_Core = []
++Security_Cryptography_DataProtection = []
++Security_DataProtection = []
++Security_EnterpriseData = []
++Security_ExchangeActiveSyncProvisioning = []
++Security_Isolation = []
++Services = []
++Services_Maps = []
++Services_Maps_Guidance = []
++Services_Maps_LocalSearch = []
++Services_Maps_OfflineMaps = []
++Services_Store = []
++Services_TargetedContent = []
++Storage = []
++Storage_AccessCache = []
++Storage_BulkAccess = []
++Storage_Compression = []
++Storage_FileProperties = []
++Storage_Pickers = []
++Storage_Pickers_Provider = []
++Storage_Provider = []
++Storage_Search = []
++Storage_Streams = []
++System = []
++System_Diagnostics = []
++System_Diagnostics_DevicePortal = []
++System_Diagnostics_Telemetry = []
++System_Diagnostics_TraceReporting = []
++System_Display = []
++System_Implementation = []
++System_Implementation_FileExplorer = []
++System_Inventory = []
++System_Power = []
++System_Profile = []
++System_Profile_SystemManufacturers = []
++System_RemoteDesktop = []
++System_RemoteDesktop_Input = []
++System_RemoteDesktop_Provider = []
++System_RemoteSystems = []
++System_Threading = []
++System_Threading_Core = []
++System_Update = []
++System_UserProfile = []
++UI = []
++UI_Accessibility = []
++UI_ApplicationSettings = []
++UI_Composition = []
++UI_Composition_Core = []
++UI_Composition_Desktop = []
++UI_Composition_Diagnostics = []
++UI_Composition_Effects = []
++UI_Composition_Interactions = []
++UI_Composition_Scenes = []
++UI_Core = []
++UI_Core_AnimationMetrics = []
++UI_Core_Preview = []
++UI_Input = []
++UI_Input_Core = []
++UI_Input_Inking = []
++UI_Input_Inking_Analysis = []
++UI_Input_Inking_Core = []
++UI_Input_Inking_Preview = []
++UI_Input_Preview = []
++UI_Input_Preview_Injection = []
++UI_Input_Spatial = []
++UI_Notifications = []
++UI_Notifications_Management = []
++UI_Notifications_Preview = []
++UI_Popups = []
++UI_Shell = []
++UI_StartScreen = []
++UI_Text = []
++UI_Text_Core = []
++UI_UIAutomation = []
++UI_UIAutomation_Core = []
++UI_ViewManagement = []
++UI_ViewManagement_Core = []
++UI_WebUI = []
++UI_WebUI_Core = []
++UI_WindowManagement = []
++UI_WindowManagement_Preview = []
++Wdk = []
++Wdk_Devices = []
++Wdk_Devices_Bluetooth = []
++Wdk_Devices_HumanInterfaceDevice = []
++Wdk_Foundation = []
++Wdk_Graphics = []
++Wdk_Graphics_Direct3D = []
++Wdk_NetworkManagement = []
++Wdk_NetworkManagement_Ndis = []
++Wdk_NetworkManagement_WindowsFilteringPlatform = []
++Wdk_Storage = []
++Wdk_Storage_FileSystem = []
++Wdk_Storage_FileSystem_Minifilters = []
++Wdk_System = []
++Wdk_System_IO = []
++Wdk_System_Memory = []
++Wdk_System_OfflineRegistry = []
++Wdk_System_Registry = []
++Wdk_System_SystemInformation = []
++Wdk_System_SystemServices = []
++Wdk_System_Threading = []
++Web = []
++Web_AtomPub = []
++Web_Http = []
++Web_Http_Diagnostics = []
++Web_Http_Filters = []
++Web_Http_Headers = []
++Web_Syndication = []
++Web_UI = []
++Web_UI_Interop = []
++Win32 = []
++Win32_AI = []
++Win32_AI_MachineLearning = []
++Win32_AI_MachineLearning_DirectML = []
++Win32_AI_MachineLearning_WinML = []
++Win32_Data = []
++Win32_Data_HtmlHelp = []
++Win32_Data_RightsManagement = []
++Win32_Data_Xml = []
++Win32_Data_Xml_MsXml = []
++Win32_Data_Xml_XmlLite = []
++Win32_Devices = []
++Win32_Devices_AllJoyn = []
++Win32_Devices_BiometricFramework = []
++Win32_Devices_Bluetooth = []
++Win32_Devices_Communication = []
++Win32_Devices_DeviceAccess = []
++Win32_Devices_DeviceAndDriverInstallation = []
++Win32_Devices_DeviceQuery = []
++Win32_Devices_Display = []
++Win32_Devices_Enumeration = []
++Win32_Devices_Enumeration_Pnp = []
++Win32_Devices_Fax = []
++Win32_Devices_FunctionDiscovery = []
++Win32_Devices_Geolocation = []
++Win32_Devices_HumanInterfaceDevice = []
++Win32_Devices_ImageAcquisition = []
++Win32_Devices_PortableDevices = []
++Win32_Devices_Properties = []
++Win32_Devices_Pwm = []
++Win32_Devices_Sensors = []
++Win32_Devices_SerialCommunication = []
++Win32_Devices_Tapi = []
++Win32_Devices_Usb = []
++Win32_Devices_WebServicesOnDevices = []
++Win32_Foundation = []
++Win32_Gaming = []
++Win32_Globalization = []
++Win32_Graphics = []
++Win32_Graphics_CompositionSwapchain = []
++Win32_Graphics_DXCore = []
++Win32_Graphics_Direct2D = []
++Win32_Graphics_Direct2D_Common = []
++Win32_Graphics_Direct3D = []
++Win32_Graphics_Direct3D10 = []
++Win32_Graphics_Direct3D11 = []
++Win32_Graphics_Direct3D11on12 = []
++Win32_Graphics_Direct3D12 = []
++Win32_Graphics_Direct3D9 = []
++Win32_Graphics_Direct3D9on12 = []
++Win32_Graphics_Direct3D_Dxc = []
++Win32_Graphics_Direct3D_Fxc = []
++Win32_Graphics_DirectComposition = []
++Win32_Graphics_DirectDraw = []
++Win32_Graphics_DirectManipulation = []
++Win32_Graphics_DirectWrite = []
++Win32_Graphics_Dwm = []
++Win32_Graphics_Dxgi = []
++Win32_Graphics_Dxgi_Common = []
++Win32_Graphics_Gdi = []
++Win32_Graphics_GdiPlus = []
++Win32_Graphics_Hlsl = []
++Win32_Graphics_Imaging = []
++Win32_Graphics_Imaging_D2D = []
++Win32_Graphics_OpenGL = []
++Win32_Graphics_Printing = []
++Win32_Graphics_Printing_PrintTicket = []
++Win32_Management = []
++Win32_Management_MobileDeviceManagementRegistration = []
++Win32_Media = []
++Win32_Media_Audio = []
++Win32_Media_Audio_Apo = []
++Win32_Media_Audio_DirectMusic = []
++Win32_Media_Audio_DirectSound = []
++Win32_Media_Audio_Endpoints = []
++Win32_Media_Audio_XAudio2 = []
++Win32_Media_DeviceManager = []
++Win32_Media_DirectShow = []
++Win32_Media_DirectShow_Tv = []
++Win32_Media_DirectShow_Xml = []
++Win32_Media_DxMediaObjects = []
++Win32_Media_KernelStreaming = []
++Win32_Media_LibrarySharingServices = []
++Win32_Media_MediaFoundation = []
++Win32_Media_MediaPlayer = []
++Win32_Media_Multimedia = []
++Win32_Media_PictureAcquisition = []
++Win32_Media_Speech = []
++Win32_Media_Streaming = []
++Win32_Media_WindowsMediaFormat = []
++Win32_NetworkManagement = []
++Win32_NetworkManagement_Dhcp = []
++Win32_NetworkManagement_Dns = []
++Win32_NetworkManagement_InternetConnectionWizard = []
++Win32_NetworkManagement_IpHelper = []
++Win32_NetworkManagement_MobileBroadband = []
++Win32_NetworkManagement_Multicast = []
++Win32_NetworkManagement_Ndis = []
++Win32_NetworkManagement_NetBios = []
++Win32_NetworkManagement_NetManagement = []
++Win32_NetworkManagement_NetShell = []
++Win32_NetworkManagement_NetworkDiagnosticsFramework = []
++Win32_NetworkManagement_NetworkPolicyServer = []
++Win32_NetworkManagement_P2P = []
++Win32_NetworkManagement_QoS = []
++Win32_NetworkManagement_Rras = []
++Win32_NetworkManagement_Snmp = []
++Win32_NetworkManagement_WNet = []
++Win32_NetworkManagement_WebDav = []
++Win32_NetworkManagement_WiFi = []
++Win32_NetworkManagement_WindowsConnectNow = []
++Win32_NetworkManagement_WindowsConnectionManager = []
++Win32_NetworkManagement_WindowsFilteringPlatform = []
++Win32_NetworkManagement_WindowsFirewall = []
++Win32_NetworkManagement_WindowsNetworkVirtualization = []
++Win32_Networking = []
++Win32_Networking_ActiveDirectory = []
++Win32_Networking_BackgroundIntelligentTransferService = []
++Win32_Networking_Clustering = []
++Win32_Networking_HttpServer = []
++Win32_Networking_Ldap = []
++Win32_Networking_NetworkListManager = []
++Win32_Networking_RemoteDifferentialCompression = []
++Win32_Networking_WebSocket = []
++Win32_Networking_WinHttp = []
++Win32_Networking_WinInet = []
++Win32_Networking_WinSock = []
++Win32_Networking_WindowsWebServices = []
++Win32_Security = []
++Win32_Security_AppLocker = []
++Win32_Security_Authentication = []
++Win32_Security_Authentication_Identity = []
++Win32_Security_Authentication_Identity_Provider = []
++Win32_Security_Authorization = []
++Win32_Security_Authorization_UI = []
++Win32_Security_ConfigurationSnapin = []
++Win32_Security_Credentials = []
++Win32_Security_Cryptography = []
++Win32_Security_Cryptography_Catalog = []
++Win32_Security_Cryptography_Certificates = []
++Win32_Security_Cryptography_Sip = []
++Win32_Security_Cryptography_UI = []
++Win32_Security_DiagnosticDataQuery = []
++Win32_Security_DirectoryServices = []
++Win32_Security_EnterpriseData = []
++Win32_Security_ExtensibleAuthenticationProtocol = []
++Win32_Security_Isolation = []
++Win32_Security_LicenseProtection = []
++Win32_Security_NetworkAccessProtection = []
++Win32_Security_Tpm = []
++Win32_Security_WinTrust = []
++Win32_Security_WinWlx = []
++Win32_Storage = []
++Win32_Storage_Cabinets = []
++Win32_Storage_CloudFilters = []
++Win32_Storage_Compression = []
++Win32_Storage_DataDeduplication = []
++Win32_Storage_DistributedFileSystem = []
++Win32_Storage_EnhancedStorage = []
++Win32_Storage_FileHistory = []
++Win32_Storage_FileServerResourceManager = []
++Win32_Storage_FileSystem = []
++Win32_Storage_Imapi = []
++Win32_Storage_IndexServer = []
++Win32_Storage_InstallableFileSystems = []
++Win32_Storage_IscsiDisc = []
++Win32_Storage_Jet = []
++Win32_Storage_Nvme = []
++Win32_Storage_OfflineFiles = []
++Win32_Storage_OperationRecorder = []
++Win32_Storage_Packaging = []
++Win32_Storage_Packaging_Appx = []
++Win32_Storage_Packaging_Opc = []
++Win32_Storage_ProjectedFileSystem = []
++Win32_Storage_StructuredStorage = []
++Win32_Storage_Vhd = []
++Win32_Storage_VirtualDiskService = []
++Win32_Storage_Vss = []
++Win32_Storage_Xps = []
++Win32_Storage_Xps_Printing = []
++Win32_System = []
++Win32_System_AddressBook = []
++Win32_System_Antimalware = []
++Win32_System_ApplicationInstallationAndServicing = []
++Win32_System_ApplicationVerifier = []
++Win32_System_AssessmentTool = []
++Win32_System_ClrHosting = []
++Win32_System_Com = []
++Win32_System_Com_CallObj = []
++Win32_System_Com_ChannelCredentials = []
++Win32_System_Com_Events = []
++Win32_System_Com_Marshal = []
++Win32_System_Com_StructuredStorage = []
++Win32_System_Com_UI = []
++Win32_System_Com_Urlmon = []
++Win32_System_ComponentServices = []
++Win32_System_Console = []
++Win32_System_Contacts = []
++Win32_System_CorrelationVector = []
++Win32_System_DataExchange = []
++Win32_System_DeploymentServices = []
++Win32_System_DesktopSharing = []
++Win32_System_DeveloperLicensing = []
++Win32_System_Diagnostics = []
++Win32_System_Diagnostics_Ceip = []
++Win32_System_Diagnostics_ClrProfiling = []
++Win32_System_Diagnostics_Debug = []
++Win32_System_Diagnostics_Debug_ActiveScript = []
++Win32_System_Diagnostics_Debug_Extensions = []
++Win32_System_Diagnostics_Etw = []
++Win32_System_Diagnostics_ProcessSnapshotting = []
++Win32_System_Diagnostics_ToolHelp = []
++Win32_System_Diagnostics_TraceLogging = []
++Win32_System_DistributedTransactionCoordinator = []
++Win32_System_Environment = []
++Win32_System_ErrorReporting = []
++Win32_System_EventCollector = []
++Win32_System_EventLog = []
++Win32_System_EventNotificationService = []
++Win32_System_GroupPolicy = []
++Win32_System_HostCompute = []
++Win32_System_HostComputeNetwork = []
++Win32_System_HostComputeSystem = []
++Win32_System_Hypervisor = []
++Win32_System_IO = []
++Win32_System_Iis = []
++Win32_System_Ioctl = []
++Win32_System_JobObjects = []
++Win32_System_Js = []
++Win32_System_Kernel = []
++Win32_System_LibraryLoader = []
++Win32_System_Mailslots = []
++Win32_System_Mapi = []
++Win32_System_Memory = []
++Win32_System_Memory_NonVolatile = []
++Win32_System_MessageQueuing = []
++Win32_System_MixedReality = []
++Win32_System_Mmc = []
++Win32_System_Ole = []
++Win32_System_ParentalControls = []
++Win32_System_PasswordManagement = []
++Win32_System_Performance = []
++Win32_System_Performance_HardwareCounterProfiling = []
++Win32_System_Pipes = []
++Win32_System_Power = []
++Win32_System_ProcessStatus = []
++Win32_System_RealTimeCommunications = []
++Win32_System_Recovery = []
++Win32_System_Registry = []
++Win32_System_RemoteAssistance = []
++Win32_System_RemoteDesktop = []
++Win32_System_RemoteManagement = []
++Win32_System_RestartManager = []
++Win32_System_Restore = []
++Win32_System_Rpc = []
++Win32_System_Search = []
++Win32_System_Search_Common = []
++Win32_System_SecurityCenter = []
++Win32_System_ServerBackup = []
++Win32_System_Services = []
++Win32_System_SettingsManagementInfrastructure = []
++Win32_System_SetupAndMigration = []
++Win32_System_Shutdown = []
++Win32_System_SideShow = []
++Win32_System_StationsAndDesktops = []
++Win32_System_SubsystemForLinux = []
++Win32_System_SystemInformation = []
++Win32_System_SystemServices = []
++Win32_System_TaskScheduler = []
++Win32_System_Threading = []
++Win32_System_Time = []
++Win32_System_TpmBaseServices = []
++Win32_System_TransactionServer = []
++Win32_System_UpdateAgent = []
++Win32_System_UpdateAssessment = []
++Win32_System_UserAccessLogging = []
++Win32_System_Variant = []
++Win32_System_VirtualDosMachines = []
++Win32_System_WinRT = []
++Win32_System_WinRT_AllJoyn = []
++Win32_System_WinRT_Composition = []
++Win32_System_WinRT_CoreInputView = []
++Win32_System_WinRT_Direct3D11 = []
++Win32_System_WinRT_Display = []
++Win32_System_WinRT_Graphics = []
++Win32_System_WinRT_Graphics_Capture = []
++Win32_System_WinRT_Graphics_Direct2D = []
++Win32_System_WinRT_Graphics_Imaging = []
++Win32_System_WinRT_Holographic = []
++Win32_System_WinRT_Isolation = []
++Win32_System_WinRT_ML = []
++Win32_System_WinRT_Media = []
++Win32_System_WinRT_Metadata = []
++Win32_System_WinRT_Pdf = []
++Win32_System_WinRT_Printing = []
++Win32_System_WinRT_Shell = []
++Win32_System_WinRT_Storage = []
++Win32_System_WindowsProgramming = []
++Win32_System_WindowsSync = []
++Win32_System_Wmi = []
++Win32_UI = []
++Win32_UI_Accessibility = []
++Win32_UI_Animation = []
++Win32_UI_ColorSystem = []
++Win32_UI_Controls = []
++Win32_UI_Controls_Dialogs = []
++Win32_UI_Controls_RichEdit = []
++Win32_UI_HiDpi = []
++Win32_UI_Input = []
++Win32_UI_Input_Ime = []
++Win32_UI_Input_Ink = []
++Win32_UI_Input_KeyboardAndMouse = []
++Win32_UI_Input_Pointer = []
++Win32_UI_Input_Radial = []
++Win32_UI_Input_Touch = []
++Win32_UI_Input_XboxController = []
++Win32_UI_InteractionContext = []
++Win32_UI_LegacyWindowsEnvironmentFeatures = []
++Win32_UI_Magnification = []
++Win32_UI_Notifications = []
++Win32_UI_Ribbon = []
++Win32_UI_Shell = []
++Win32_UI_Shell_Common = []
++Win32_UI_Shell_PropertiesSystem = []
++Win32_UI_TabletPC = []
++Win32_UI_TextServices = []
++Win32_UI_WindowsAndMessaging = []
++Win32_UI_Wpf = []
++Win32_Web = []
++Win32_Web_InternetExplorer = []
++default = []
+ deprecated = []
+ docs = []
+ implement = []
+-std = ["windows-core/std"]
++std = []
+ [lints.rust]
+ missing_docs = "warn"
diff --git a/tests/configs/windows-0.58/debian/patches/remove-cycles.patch~ b/tests/configs/windows-0.58/debian/patches/remove-cycles.patch~
new file mode 100644 (file)
index 0000000..42f7eb7
--- /dev/null
@@ -0,0 +1,1389 @@
+Index: rust-windows-0.54-0.54.0/Cargo.toml
+===================================================================
+--- rust-windows-0.54-0.54.0.orig/Cargo.toml
++++ rust-windows-0.54-0.54.0/Cargo.toml
+@@ -46,699 +46,696 @@ optional = true
+ version = "0.52.3"
+ [features]
+-AI = ["Foundation"]
+-AI_MachineLearning = ["AI"]
+-ApplicationModel = ["Foundation"]
+-ApplicationModel_Activation = ["ApplicationModel"]
+-ApplicationModel_AppExtensions = ["ApplicationModel"]
+-ApplicationModel_AppService = ["ApplicationModel"]
+-ApplicationModel_Appointments = ["ApplicationModel"]
+-ApplicationModel_Appointments_AppointmentsProvider = ["ApplicationModel_Appointments"]
+-ApplicationModel_Appointments_DataProvider = ["ApplicationModel_Appointments"]
+-ApplicationModel_Background = ["ApplicationModel"]
+-ApplicationModel_Calls = ["ApplicationModel"]
+-ApplicationModel_Calls_Background = ["ApplicationModel_Calls"]
+-ApplicationModel_Calls_Provider = ["ApplicationModel_Calls"]
+-ApplicationModel_Chat = ["ApplicationModel"]
+-ApplicationModel_CommunicationBlocking = ["ApplicationModel"]
+-ApplicationModel_Contacts = ["ApplicationModel"]
+-ApplicationModel_Contacts_DataProvider = ["ApplicationModel_Contacts"]
+-ApplicationModel_Contacts_Provider = ["ApplicationModel_Contacts"]
+-ApplicationModel_ConversationalAgent = ["ApplicationModel"]
+-ApplicationModel_Core = ["ApplicationModel"]
+-ApplicationModel_DataTransfer = ["ApplicationModel"]
+-ApplicationModel_DataTransfer_DragDrop = ["ApplicationModel_DataTransfer"]
+-ApplicationModel_DataTransfer_DragDrop_Core = ["ApplicationModel_DataTransfer_DragDrop"]
+-ApplicationModel_DataTransfer_ShareTarget = ["ApplicationModel_DataTransfer"]
+-ApplicationModel_Email = ["ApplicationModel"]
+-ApplicationModel_Email_DataProvider = ["ApplicationModel_Email"]
+-ApplicationModel_ExtendedExecution = ["ApplicationModel"]
+-ApplicationModel_ExtendedExecution_Foreground = ["ApplicationModel_ExtendedExecution"]
+-ApplicationModel_Holographic = ["ApplicationModel"]
+-ApplicationModel_LockScreen = ["ApplicationModel"]
+-ApplicationModel_Payments = ["ApplicationModel"]
+-ApplicationModel_Payments_Provider = ["ApplicationModel_Payments"]
+-ApplicationModel_Preview = ["ApplicationModel"]
+-ApplicationModel_Preview_Holographic = ["ApplicationModel_Preview"]
+-ApplicationModel_Preview_InkWorkspace = ["ApplicationModel_Preview"]
+-ApplicationModel_Preview_Notes = ["ApplicationModel_Preview"]
+-ApplicationModel_Resources = ["ApplicationModel"]
+-ApplicationModel_Resources_Core = ["ApplicationModel_Resources"]
+-ApplicationModel_Resources_Management = ["ApplicationModel_Resources"]
+-ApplicationModel_Search = ["ApplicationModel"]
+-ApplicationModel_Search_Core = ["ApplicationModel_Search"]
+-ApplicationModel_Store = ["ApplicationModel"]
+-ApplicationModel_Store_LicenseManagement = ["ApplicationModel_Store"]
+-ApplicationModel_Store_Preview = ["ApplicationModel_Store"]
+-ApplicationModel_Store_Preview_InstallControl = ["ApplicationModel_Store_Preview"]
+-ApplicationModel_UserActivities = ["ApplicationModel"]
+-ApplicationModel_UserActivities_Core = ["ApplicationModel_UserActivities"]
+-ApplicationModel_UserDataAccounts = ["ApplicationModel"]
+-ApplicationModel_UserDataAccounts_Provider = ["ApplicationModel_UserDataAccounts"]
+-ApplicationModel_UserDataAccounts_SystemAccess = ["ApplicationModel_UserDataAccounts"]
+-ApplicationModel_UserDataTasks = ["ApplicationModel"]
+-ApplicationModel_UserDataTasks_DataProvider = ["ApplicationModel_UserDataTasks"]
+-ApplicationModel_VoiceCommands = ["ApplicationModel"]
+-ApplicationModel_Wallet = ["ApplicationModel"]
+-ApplicationModel_Wallet_System = ["ApplicationModel_Wallet"]
+-Data = ["Foundation"]
+-Data_Html = ["Data"]
+-Data_Json = ["Data"]
+-Data_Pdf = ["Data"]
+-Data_Text = ["Data"]
+-Data_Xml = ["Data"]
+-Data_Xml_Dom = ["Data_Xml"]
+-Data_Xml_Xsl = ["Data_Xml"]
+-Devices = ["Foundation"]
+-Devices_Adc = ["Devices"]
+-Devices_Adc_Provider = ["Devices_Adc"]
+-Devices_Background = ["Devices"]
+-Devices_Bluetooth = ["Devices"]
+-Devices_Bluetooth_Advertisement = ["Devices_Bluetooth"]
+-Devices_Bluetooth_Background = ["Devices_Bluetooth"]
+-Devices_Bluetooth_GenericAttributeProfile = ["Devices_Bluetooth"]
+-Devices_Bluetooth_Rfcomm = ["Devices_Bluetooth"]
+-Devices_Custom = ["Devices"]
+-Devices_Display = ["Devices"]
+-Devices_Display_Core = ["Devices_Display"]
+-Devices_Enumeration = ["Devices"]
+-Devices_Enumeration_Pnp = ["Devices_Enumeration"]
+-Devices_Geolocation = ["Devices"]
+-Devices_Geolocation_Geofencing = ["Devices_Geolocation"]
+-Devices_Geolocation_Provider = ["Devices_Geolocation"]
+-Devices_Gpio = ["Devices"]
+-Devices_Gpio_Provider = ["Devices_Gpio"]
+-Devices_Haptics = ["Devices"]
+-Devices_HumanInterfaceDevice = ["Devices"]
+-Devices_I2c = ["Devices"]
+-Devices_I2c_Provider = ["Devices_I2c"]
+-Devices_Input = ["Devices"]
+-Devices_Input_Preview = ["Devices_Input"]
+-Devices_Lights = ["Devices"]
+-Devices_Lights_Effects = ["Devices_Lights"]
+-Devices_Midi = ["Devices"]
+-Devices_PointOfService = ["Devices"]
+-Devices_PointOfService_Provider = ["Devices_PointOfService"]
+-Devices_Portable = ["Devices"]
+-Devices_Power = ["Devices"]
+-Devices_Printers = ["Devices"]
+-Devices_Printers_Extensions = ["Devices_Printers"]
+-Devices_Pwm = ["Devices"]
+-Devices_Pwm_Provider = ["Devices_Pwm"]
+-Devices_Radios = ["Devices"]
+-Devices_Scanners = ["Devices"]
+-Devices_Sensors = ["Devices"]
+-Devices_Sensors_Custom = ["Devices_Sensors"]
+-Devices_SerialCommunication = ["Devices"]
+-Devices_SmartCards = ["Devices"]
+-Devices_Sms = ["Devices"]
+-Devices_Spi = ["Devices"]
+-Devices_Spi_Provider = ["Devices_Spi"]
+-Devices_Usb = ["Devices"]
+-Devices_WiFi = ["Devices"]
+-Devices_WiFiDirect = ["Devices"]
+-Devices_WiFiDirect_Services = ["Devices_WiFiDirect"]
+-Embedded = ["Foundation"]
+-Embedded_DeviceLockdown = ["Embedded"]
++AI = []
++AI_MachineLearning = []
++ApplicationModel = []
++ApplicationModel_Activation = []
++ApplicationModel_AppExtensions = []
++ApplicationModel_AppService = []
++ApplicationModel_Appointments = []
++ApplicationModel_Appointments_AppointmentsProvider = []
++ApplicationModel_Appointments_DataProvider = []
++ApplicationModel_Background = []
++ApplicationModel_Calls = []
++ApplicationModel_Calls_Background = []
++ApplicationModel_Calls_Provider = []
++ApplicationModel_Chat = []
++ApplicationModel_CommunicationBlocking = []
++ApplicationModel_Contacts = []
++ApplicationModel_Contacts_DataProvider = []
++ApplicationModel_Contacts_Provider = []
++ApplicationModel_ConversationalAgent = []
++ApplicationModel_Core = []
++ApplicationModel_DataTransfer = []
++ApplicationModel_DataTransfer_DragDrop = []
++ApplicationModel_DataTransfer_DragDrop_Core = []
++ApplicationModel_DataTransfer_ShareTarget = []
++ApplicationModel_Email = []
++ApplicationModel_Email_DataProvider = []
++ApplicationModel_ExtendedExecution = []
++ApplicationModel_ExtendedExecution_Foreground = []
++ApplicationModel_Holographic = []
++ApplicationModel_LockScreen = []
++ApplicationModel_Payments = []
++ApplicationModel_Payments_Provider = []
++ApplicationModel_Preview = []
++ApplicationModel_Preview_Holographic = []
++ApplicationModel_Preview_InkWorkspace = []
++ApplicationModel_Preview_Notes = []
++ApplicationModel_Resources = []
++ApplicationModel_Resources_Core = []
++ApplicationModel_Resources_Management = []
++ApplicationModel_Search = []
++ApplicationModel_Search_Core = []
++ApplicationModel_Store = []
++ApplicationModel_Store_LicenseManagement = []
++ApplicationModel_Store_Preview = []
++ApplicationModel_Store_Preview_InstallControl = []
++ApplicationModel_UserActivities = []
++ApplicationModel_UserActivities_Core = []
++ApplicationModel_UserDataAccounts = []
++ApplicationModel_UserDataAccounts_Provider = []
++ApplicationModel_UserDataAccounts_SystemAccess = []
++ApplicationModel_UserDataTasks = []
++ApplicationModel_UserDataTasks_DataProvider = []
++ApplicationModel_VoiceCommands = []
++ApplicationModel_Wallet = []
++ApplicationModel_Wallet_System = []
++Data = []
++Data_Html = []
++Data_Json = []
++Data_Pdf = []
++Data_Text = []
++Data_Xml = []
++Data_Xml_Dom = []
++Data_Xml_Xsl = []
++Devices = []
++Devices_Adc = []
++Devices_Adc_Provider = []
++Devices_Background = []
++Devices_Bluetooth = []
++Devices_Bluetooth_Advertisement = []
++Devices_Bluetooth_Background = []
++Devices_Bluetooth_GenericAttributeProfile = []
++Devices_Bluetooth_Rfcomm = []
++Devices_Custom = []
++Devices_Display = []
++Devices_Display_Core = []
++Devices_Enumeration = []
++Devices_Enumeration_Pnp = []
++Devices_Geolocation = []
++Devices_Geolocation_Geofencing = []
++Devices_Geolocation_Provider = []
++Devices_Gpio = []
++Devices_Gpio_Provider = []
++Devices_Haptics = []
++Devices_HumanInterfaceDevice = []
++Devices_I2c = []
++Devices_I2c_Provider = []
++Devices_Input = []
++Devices_Input_Preview = []
++Devices_Lights = []
++Devices_Lights_Effects = []
++Devices_Midi = []
++Devices_PointOfService = []
++Devices_PointOfService_Provider = []
++Devices_Portable = []
++Devices_Power = []
++Devices_Printers = []
++Devices_Printers_Extensions = []
++Devices_Pwm = []
++Devices_Pwm_Provider = []
++Devices_Radios = []
++Devices_Scanners = []
++Devices_Sensors = []
++Devices_Sensors_Custom = []
++Devices_SerialCommunication = []
++Devices_SmartCards = []
++Devices_Sms = []
++Devices_Spi = []
++Devices_Spi_Provider = []
++Devices_Usb = []
++Devices_WiFi = []
++Devices_WiFiDirect = []
++Devices_WiFiDirect_Services = []
++Embedded = []
++Embedded_DeviceLockdown = []
+ Foundation = []
+-Foundation_Collections = ["Foundation"]
+-Foundation_Diagnostics = ["Foundation"]
+-Foundation_Metadata = ["Foundation"]
+-Foundation_Numerics = ["Foundation"]
+-Gaming = ["Foundation"]
+-Gaming_Input = ["Gaming"]
+-Gaming_Input_Custom = ["Gaming_Input"]
+-Gaming_Input_ForceFeedback = ["Gaming_Input"]
+-Gaming_Input_Preview = ["Gaming_Input"]
+-Gaming_Preview = ["Gaming"]
+-Gaming_Preview_GamesEnumeration = ["Gaming_Preview"]
+-Gaming_UI = ["Gaming"]
+-Gaming_XboxLive = ["Gaming"]
+-Gaming_XboxLive_Storage = ["Gaming_XboxLive"]
+-Globalization = ["Foundation"]
+-Globalization_Collation = ["Globalization"]
+-Globalization_DateTimeFormatting = ["Globalization"]
+-Globalization_Fonts = ["Globalization"]
+-Globalization_NumberFormatting = ["Globalization"]
+-Globalization_PhoneNumberFormatting = ["Globalization"]
+-Graphics = ["Foundation"]
+-Graphics_Capture = ["Graphics"]
+-Graphics_DirectX = ["Graphics"]
+-Graphics_DirectX_Direct3D11 = ["Graphics_DirectX"]
+-Graphics_Display = ["Graphics"]
+-Graphics_Display_Core = ["Graphics_Display"]
+-Graphics_Effects = ["Graphics"]
+-Graphics_Holographic = ["Graphics"]
+-Graphics_Imaging = ["Graphics"]
+-Graphics_Printing = ["Graphics"]
+-Graphics_Printing3D = ["Graphics"]
+-Graphics_Printing_OptionDetails = ["Graphics_Printing"]
+-Graphics_Printing_PrintSupport = ["Graphics_Printing"]
+-Graphics_Printing_PrintTicket = ["Graphics_Printing"]
+-Graphics_Printing_Workflow = ["Graphics_Printing"]
+-Management = ["Foundation"]
+-Management_Core = ["Management"]
+-Management_Deployment = ["Management"]
+-Management_Deployment_Preview = ["Management_Deployment"]
+-Management_Policies = ["Management"]
+-Management_Update = ["Management"]
+-Management_Workplace = ["Management"]
+-Media = ["Foundation"]
+-Media_AppBroadcasting = ["Media"]
+-Media_AppRecording = ["Media"]
+-Media_Audio = ["Media"]
+-Media_Capture = ["Media"]
+-Media_Capture_Core = ["Media_Capture"]
+-Media_Capture_Frames = ["Media_Capture"]
+-Media_Casting = ["Media"]
+-Media_ClosedCaptioning = ["Media"]
+-Media_ContentRestrictions = ["Media"]
+-Media_Control = ["Media"]
+-Media_Core = ["Media"]
+-Media_Core_Preview = ["Media_Core"]
+-Media_Devices = ["Media"]
+-Media_Devices_Core = ["Media_Devices"]
+-Media_DialProtocol = ["Media"]
+-Media_Editing = ["Media"]
+-Media_Effects = ["Media"]
+-Media_FaceAnalysis = ["Media"]
+-Media_Import = ["Media"]
+-Media_MediaProperties = ["Media"]
+-Media_Miracast = ["Media"]
+-Media_Ocr = ["Media"]
+-Media_PlayTo = ["Media"]
+-Media_Playback = ["Media"]
+-Media_Playlists = ["Media"]
+-Media_Protection = ["Media"]
+-Media_Protection_PlayReady = ["Media_Protection"]
+-Media_Render = ["Media"]
+-Media_SpeechRecognition = ["Media"]
+-Media_SpeechSynthesis = ["Media"]
+-Media_Streaming = ["Media"]
+-Media_Streaming_Adaptive = ["Media_Streaming"]
+-Media_Transcoding = ["Media"]
+-Networking = ["Foundation"]
+-Networking_BackgroundTransfer = ["Networking"]
+-Networking_Connectivity = ["Networking"]
+-Networking_NetworkOperators = ["Networking"]
+-Networking_Proximity = ["Networking"]
+-Networking_PushNotifications = ["Networking"]
+-Networking_ServiceDiscovery = ["Networking"]
+-Networking_ServiceDiscovery_Dnssd = ["Networking_ServiceDiscovery"]
+-Networking_Sockets = ["Networking"]
+-Networking_Vpn = ["Networking"]
+-Networking_XboxLive = ["Networking"]
+-Perception = ["Foundation"]
+-Perception_Automation = ["Perception"]
+-Perception_Automation_Core = ["Perception_Automation"]
+-Perception_People = ["Perception"]
+-Perception_Spatial = ["Perception"]
+-Perception_Spatial_Preview = ["Perception_Spatial"]
+-Perception_Spatial_Surfaces = ["Perception_Spatial"]
+-Phone = ["Foundation"]
+-Phone_ApplicationModel = ["Phone"]
+-Phone_Devices = ["Phone"]
+-Phone_Devices_Notification = ["Phone_Devices"]
+-Phone_Devices_Power = ["Phone_Devices"]
+-Phone_Management = ["Phone"]
+-Phone_Management_Deployment = ["Phone_Management"]
+-Phone_Media = ["Phone"]
+-Phone_Media_Devices = ["Phone_Media"]
+-Phone_Notification = ["Phone"]
+-Phone_Notification_Management = ["Phone_Notification"]
+-Phone_PersonalInformation = ["Phone"]
+-Phone_PersonalInformation_Provisioning = ["Phone_PersonalInformation"]
+-Phone_Speech = ["Phone"]
+-Phone_Speech_Recognition = ["Phone_Speech"]
+-Phone_StartScreen = ["Phone"]
+-Phone_System = ["Phone"]
+-Phone_System_Power = ["Phone_System"]
+-Phone_System_Profile = ["Phone_System"]
+-Phone_System_UserProfile = ["Phone_System"]
+-Phone_System_UserProfile_GameServices = ["Phone_System_UserProfile"]
+-Phone_System_UserProfile_GameServices_Core = ["Phone_System_UserProfile_GameServices"]
+-Phone_UI = ["Phone"]
+-Phone_UI_Input = ["Phone_UI"]
+-Security = ["Foundation"]
+-Security_Authentication = ["Security"]
+-Security_Authentication_Identity = ["Security_Authentication"]
+-Security_Authentication_Identity_Core = ["Security_Authentication_Identity"]
+-Security_Authentication_OnlineId = ["Security_Authentication"]
+-Security_Authentication_Web = ["Security_Authentication"]
+-Security_Authentication_Web_Core = ["Security_Authentication_Web"]
+-Security_Authentication_Web_Provider = ["Security_Authentication_Web"]
+-Security_Authorization = ["Security"]
+-Security_Authorization_AppCapabilityAccess = ["Security_Authorization"]
+-Security_Credentials = ["Security"]
+-Security_Credentials_UI = ["Security_Credentials"]
+-Security_Cryptography = ["Security"]
+-Security_Cryptography_Certificates = ["Security_Cryptography"]
+-Security_Cryptography_Core = ["Security_Cryptography"]
+-Security_Cryptography_DataProtection = ["Security_Cryptography"]
+-Security_DataProtection = ["Security"]
+-Security_EnterpriseData = ["Security"]
+-Security_ExchangeActiveSyncProvisioning = ["Security"]
+-Security_Isolation = ["Security"]
+-Services = ["Foundation"]
+-Services_Maps = ["Services"]
+-Services_Maps_Guidance = ["Services_Maps"]
+-Services_Maps_LocalSearch = ["Services_Maps"]
+-Services_Maps_OfflineMaps = ["Services_Maps"]
+-Services_Store = ["Services"]
+-Services_TargetedContent = ["Services"]
+-Storage = ["Foundation"]
+-Storage_AccessCache = ["Storage"]
+-Storage_BulkAccess = ["Storage"]
+-Storage_Compression = ["Storage"]
+-Storage_FileProperties = ["Storage"]
+-Storage_Pickers = ["Storage"]
+-Storage_Pickers_Provider = ["Storage_Pickers"]
+-Storage_Provider = ["Storage"]
+-Storage_Search = ["Storage"]
+-Storage_Streams = ["Storage"]
+-System = ["Foundation"]
+-System_Diagnostics = ["System"]
+-System_Diagnostics_DevicePortal = ["System_Diagnostics"]
+-System_Diagnostics_Telemetry = ["System_Diagnostics"]
+-System_Diagnostics_TraceReporting = ["System_Diagnostics"]
+-System_Display = ["System"]
+-System_Implementation = ["System"]
+-System_Implementation_FileExplorer = ["System_Implementation"]
+-System_Inventory = ["System"]
+-System_Power = ["System"]
+-System_Profile = ["System"]
+-System_Profile_SystemManufacturers = ["System_Profile"]
+-System_RemoteDesktop = ["System"]
+-System_RemoteDesktop_Input = ["System_RemoteDesktop"]
+-System_RemoteDesktop_Provider = ["System_RemoteDesktop"]
+-System_RemoteSystems = ["System"]
+-System_Threading = ["System"]
+-System_Threading_Core = ["System_Threading"]
+-System_Update = ["System"]
+-System_UserProfile = ["System"]
+-UI = ["Foundation"]
+-UI_Accessibility = ["UI"]
+-UI_ApplicationSettings = ["UI"]
+-UI_Composition = ["UI"]
+-UI_Composition_Core = ["UI_Composition"]
+-UI_Composition_Desktop = ["UI_Composition"]
+-UI_Composition_Diagnostics = ["UI_Composition"]
+-UI_Composition_Effects = ["UI_Composition"]
+-UI_Composition_Interactions = ["UI_Composition"]
+-UI_Composition_Scenes = ["UI_Composition"]
+-UI_Core = ["UI"]
+-UI_Core_AnimationMetrics = ["UI_Core"]
+-UI_Core_Preview = ["UI_Core"]
+-UI_Input = ["UI"]
+-UI_Input_Core = ["UI_Input"]
+-UI_Input_Inking = ["UI_Input"]
+-UI_Input_Inking_Analysis = ["UI_Input_Inking"]
+-UI_Input_Inking_Core = ["UI_Input_Inking"]
+-UI_Input_Inking_Preview = ["UI_Input_Inking"]
+-UI_Input_Preview = ["UI_Input"]
+-UI_Input_Preview_Injection = ["UI_Input_Preview"]
+-UI_Input_Spatial = ["UI_Input"]
+-UI_Notifications = ["UI"]
+-UI_Notifications_Management = ["UI_Notifications"]
+-UI_Notifications_Preview = ["UI_Notifications"]
+-UI_Popups = ["UI"]
+-UI_Shell = ["UI"]
+-UI_StartScreen = ["UI"]
+-UI_Text = ["UI"]
+-UI_Text_Core = ["UI_Text"]
+-UI_UIAutomation = ["UI"]
+-UI_UIAutomation_Core = ["UI_UIAutomation"]
+-UI_ViewManagement = ["UI"]
+-UI_ViewManagement_Core = ["UI_ViewManagement"]
+-UI_WebUI = ["UI"]
+-UI_WebUI_Core = ["UI_WebUI"]
+-UI_WindowManagement = ["UI"]
+-UI_WindowManagement_Preview = ["UI_WindowManagement"]
+-Wdk = ["Win32_Foundation"]
+-Wdk_Devices = ["Wdk"]
+-Wdk_Devices_HumanInterfaceDevice = ["Wdk_Devices"]
+-Wdk_Foundation = ["Wdk"]
+-Wdk_Graphics = ["Wdk"]
+-Wdk_Graphics_Direct3D = ["Wdk_Graphics"]
+-Wdk_NetworkManagement = ["Wdk"]
+-Wdk_NetworkManagement_Ndis = ["Wdk_NetworkManagement"]
+-Wdk_NetworkManagement_WindowsFilteringPlatform = ["Wdk_NetworkManagement"]
+-Wdk_Storage = ["Wdk"]
+-Wdk_Storage_FileSystem = ["Wdk_Storage"]
+-Wdk_Storage_FileSystem_Minifilters = ["Wdk_Storage_FileSystem"]
+-Wdk_System = ["Wdk"]
+-Wdk_System_IO = ["Wdk_System"]
+-Wdk_System_OfflineRegistry = ["Wdk_System"]
+-Wdk_System_Registry = ["Wdk_System"]
+-Wdk_System_SystemInformation = ["Wdk_System"]
+-Wdk_System_SystemServices = ["Wdk_System"]
+-Wdk_System_Threading = ["Wdk_System"]
+-Web = ["Foundation"]
+-Web_AtomPub = ["Web"]
+-Web_Http = ["Web"]
+-Web_Http_Diagnostics = ["Web_Http"]
+-Web_Http_Filters = ["Web_Http"]
+-Web_Http_Headers = ["Web_Http"]
+-Web_Syndication = ["Web"]
+-Web_UI = ["Web"]
+-Web_UI_Interop = ["Web_UI"]
+-Win32 = ["Win32_Foundation"]
+-Win32_AI = ["Win32"]
+-Win32_AI_MachineLearning = ["Win32_AI"]
+-Win32_AI_MachineLearning_DirectML = ["Win32_AI_MachineLearning"]
+-Win32_AI_MachineLearning_WinML = ["Win32_AI_MachineLearning"]
+-Win32_Data = ["Win32"]
+-Win32_Data_HtmlHelp = ["Win32_Data"]
+-Win32_Data_RightsManagement = ["Win32_Data"]
+-Win32_Data_Xml = ["Win32_Data"]
+-Win32_Data_Xml_MsXml = ["Win32_Data_Xml"]
+-Win32_Data_Xml_XmlLite = ["Win32_Data_Xml"]
+-Win32_Devices = ["Win32"]
+-Win32_Devices_AllJoyn = ["Win32_Devices"]
+-Win32_Devices_BiometricFramework = ["Win32_Devices"]
+-Win32_Devices_Bluetooth = ["Win32_Devices"]
+-Win32_Devices_Communication = ["Win32_Devices"]
+-Win32_Devices_DeviceAccess = ["Win32_Devices"]
+-Win32_Devices_DeviceAndDriverInstallation = ["Win32_Devices"]
+-Win32_Devices_DeviceQuery = ["Win32_Devices"]
+-Win32_Devices_Display = ["Win32_Devices"]
+-Win32_Devices_Enumeration = ["Win32_Devices"]
+-Win32_Devices_Enumeration_Pnp = ["Win32_Devices_Enumeration"]
+-Win32_Devices_Fax = ["Win32_Devices"]
+-Win32_Devices_FunctionDiscovery = ["Win32_Devices"]
+-Win32_Devices_Geolocation = ["Win32_Devices"]
+-Win32_Devices_HumanInterfaceDevice = ["Win32_Devices"]
+-Win32_Devices_ImageAcquisition = ["Win32_Devices"]
+-Win32_Devices_PortableDevices = ["Win32_Devices"]
+-Win32_Devices_Properties = ["Win32_Devices"]
+-Win32_Devices_Pwm = ["Win32_Devices"]
+-Win32_Devices_Sensors = ["Win32_Devices"]
+-Win32_Devices_SerialCommunication = ["Win32_Devices"]
+-Win32_Devices_Tapi = ["Win32_Devices"]
+-Win32_Devices_Usb = ["Win32_Devices"]
+-Win32_Devices_WebServicesOnDevices = ["Win32_Devices"]
+-Win32_Foundation = ["Win32"]
+-Win32_Gaming = ["Win32"]
+-Win32_Globalization = ["Win32"]
+-Win32_Graphics = ["Win32"]
+-Win32_Graphics_CompositionSwapchain = ["Win32_Graphics"]
+-Win32_Graphics_DXCore = ["Win32_Graphics"]
+-Win32_Graphics_Direct2D = ["Win32_Graphics"]
+-Win32_Graphics_Direct2D_Common = ["Win32_Graphics_Direct2D"]
+-Win32_Graphics_Direct3D = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D10 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D11 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D11on12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D9 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D9on12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D_Dxc = ["Win32_Graphics_Direct3D"]
+-Win32_Graphics_Direct3D_Fxc = ["Win32_Graphics_Direct3D"]
+-Win32_Graphics_DirectComposition = ["Win32_Graphics"]
+-Win32_Graphics_DirectDraw = ["Win32_Graphics"]
+-Win32_Graphics_DirectManipulation = ["Win32_Graphics"]
+-Win32_Graphics_DirectWrite = ["Win32_Graphics"]
+-Win32_Graphics_Dwm = ["Win32_Graphics"]
+-Win32_Graphics_Dxgi = ["Win32_Graphics"]
+-Win32_Graphics_Dxgi_Common = ["Win32_Graphics_Dxgi"]
+-Win32_Graphics_Gdi = ["Win32_Graphics"]
+-Win32_Graphics_GdiPlus = ["Win32_Graphics"]
+-Win32_Graphics_Hlsl = ["Win32_Graphics"]
+-Win32_Graphics_Imaging = ["Win32_Graphics"]
+-Win32_Graphics_Imaging_D2D = ["Win32_Graphics_Imaging"]
+-Win32_Graphics_OpenGL = ["Win32_Graphics"]
+-Win32_Graphics_Printing = ["Win32_Graphics"]
+-Win32_Graphics_Printing_PrintTicket = ["Win32_Graphics_Printing"]
+-Win32_Management = ["Win32"]
+-Win32_Management_MobileDeviceManagementRegistration = ["Win32_Management"]
+-Win32_Media = ["Win32"]
+-Win32_Media_Audio = ["Win32_Media"]
+-Win32_Media_Audio_Apo = ["Win32_Media_Audio"]
+-Win32_Media_Audio_DirectMusic = ["Win32_Media_Audio"]
+-Win32_Media_Audio_DirectSound = ["Win32_Media_Audio"]
+-Win32_Media_Audio_Endpoints = ["Win32_Media_Audio"]
+-Win32_Media_Audio_XAudio2 = ["Win32_Media_Audio"]
+-Win32_Media_DeviceManager = ["Win32_Media"]
+-Win32_Media_DirectShow = ["Win32_Media"]
+-Win32_Media_DirectShow_Tv = ["Win32_Media_DirectShow"]
+-Win32_Media_DirectShow_Xml = ["Win32_Media_DirectShow"]
+-Win32_Media_DxMediaObjects = ["Win32_Media"]
+-Win32_Media_KernelStreaming = ["Win32_Media"]
+-Win32_Media_LibrarySharingServices = ["Win32_Media"]
+-Win32_Media_MediaFoundation = ["Win32_Media"]
+-Win32_Media_MediaPlayer = ["Win32_Media"]
+-Win32_Media_Multimedia = ["Win32_Media"]
+-Win32_Media_PictureAcquisition = ["Win32_Media"]
+-Win32_Media_Speech = ["Win32_Media"]
+-Win32_Media_Streaming = ["Win32_Media"]
+-Win32_Media_WindowsMediaFormat = ["Win32_Media"]
+-Win32_NetworkManagement = ["Win32"]
+-Win32_NetworkManagement_Dhcp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Dns = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_InternetConnectionWizard = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_IpHelper = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_MobileBroadband = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Multicast = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Ndis = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetBios = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetManagement = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetShell = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetworkDiagnosticsFramework = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetworkPolicyServer = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_P2P = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_QoS = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Rras = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Snmp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WNet = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WebDav = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WiFi = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsConnectNow = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsConnectionManager = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFilteringPlatform = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFirewall = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsNetworkVirtualization = ["Win32_NetworkManagement"]
+-Win32_Networking = ["Win32"]
+-Win32_Networking_ActiveDirectory = ["Win32_Networking"]
+-Win32_Networking_BackgroundIntelligentTransferService = ["Win32_Networking"]
+-Win32_Networking_Clustering = ["Win32_Networking"]
+-Win32_Networking_HttpServer = ["Win32_Networking"]
+-Win32_Networking_Ldap = ["Win32_Networking"]
+-Win32_Networking_NetworkListManager = ["Win32_Networking"]
+-Win32_Networking_RemoteDifferentialCompression = ["Win32_Networking"]
+-Win32_Networking_WebSocket = ["Win32_Networking"]
+-Win32_Networking_WinHttp = ["Win32_Networking"]
+-Win32_Networking_WinInet = ["Win32_Networking"]
+-Win32_Networking_WinSock = ["Win32_Networking"]
+-Win32_Networking_WindowsWebServices = ["Win32_Networking"]
+-Win32_Security = ["Win32"]
+-Win32_Security_AppLocker = ["Win32_Security"]
+-Win32_Security_Authentication = ["Win32_Security"]
+-Win32_Security_Authentication_Identity = ["Win32_Security_Authentication"]
+-Win32_Security_Authentication_Identity_Provider = ["Win32_Security_Authentication_Identity"]
+-Win32_Security_Authorization = ["Win32_Security"]
+-Win32_Security_Authorization_UI = ["Win32_Security_Authorization"]
+-Win32_Security_ConfigurationSnapin = ["Win32_Security"]
+-Win32_Security_Credentials = ["Win32_Security"]
+-Win32_Security_Cryptography = ["Win32_Security"]
+-Win32_Security_Cryptography_Catalog = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Certificates = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Sip = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_UI = ["Win32_Security_Cryptography"]
+-Win32_Security_DiagnosticDataQuery = ["Win32_Security"]
+-Win32_Security_DirectoryServices = ["Win32_Security"]
+-Win32_Security_EnterpriseData = ["Win32_Security"]
+-Win32_Security_ExtensibleAuthenticationProtocol = ["Win32_Security"]
+-Win32_Security_Isolation = ["Win32_Security"]
+-Win32_Security_LicenseProtection = ["Win32_Security"]
+-Win32_Security_NetworkAccessProtection = ["Win32_Security"]
+-Win32_Security_Tpm = ["Win32_Security"]
+-Win32_Security_WinTrust = ["Win32_Security"]
+-Win32_Security_WinWlx = ["Win32_Security"]
+-Win32_Storage = ["Win32"]
+-Win32_Storage_Cabinets = ["Win32_Storage"]
+-Win32_Storage_CloudFilters = ["Win32_Storage"]
+-Win32_Storage_Compression = ["Win32_Storage"]
+-Win32_Storage_DataDeduplication = ["Win32_Storage"]
+-Win32_Storage_DistributedFileSystem = ["Win32_Storage"]
+-Win32_Storage_EnhancedStorage = ["Win32_Storage"]
+-Win32_Storage_FileHistory = ["Win32_Storage"]
+-Win32_Storage_FileServerResourceManager = ["Win32_Storage"]
+-Win32_Storage_FileSystem = ["Win32_Storage"]
+-Win32_Storage_Imapi = ["Win32_Storage"]
+-Win32_Storage_IndexServer = ["Win32_Storage"]
+-Win32_Storage_InstallableFileSystems = ["Win32_Storage"]
+-Win32_Storage_IscsiDisc = ["Win32_Storage"]
+-Win32_Storage_Jet = ["Win32_Storage"]
+-Win32_Storage_Nvme = ["Win32_Storage"]
+-Win32_Storage_OfflineFiles = ["Win32_Storage"]
+-Win32_Storage_OperationRecorder = ["Win32_Storage"]
+-Win32_Storage_Packaging = ["Win32_Storage"]
+-Win32_Storage_Packaging_Appx = ["Win32_Storage_Packaging"]
+-Win32_Storage_Packaging_Opc = ["Win32_Storage_Packaging"]
+-Win32_Storage_ProjectedFileSystem = ["Win32_Storage"]
+-Win32_Storage_StructuredStorage = ["Win32_Storage"]
+-Win32_Storage_Vhd = ["Win32_Storage"]
+-Win32_Storage_VirtualDiskService = ["Win32_Storage"]
+-Win32_Storage_Vss = ["Win32_Storage"]
+-Win32_Storage_Xps = ["Win32_Storage"]
+-Win32_Storage_Xps_Printing = ["Win32_Storage_Xps"]
+-Win32_System = ["Win32"]
+-Win32_System_AddressBook = ["Win32_System"]
+-Win32_System_Antimalware = ["Win32_System"]
+-Win32_System_ApplicationInstallationAndServicing = ["Win32_System"]
+-Win32_System_ApplicationVerifier = ["Win32_System"]
+-Win32_System_AssessmentTool = ["Win32_System"]
+-Win32_System_ClrHosting = ["Win32_System"]
+-Win32_System_Com = ["Win32_System"]
+-Win32_System_Com_CallObj = ["Win32_System_Com"]
+-Win32_System_Com_ChannelCredentials = ["Win32_System_Com"]
+-Win32_System_Com_Events = ["Win32_System_Com"]
+-Win32_System_Com_Marshal = ["Win32_System_Com"]
+-Win32_System_Com_StructuredStorage = ["Win32_System_Com"]
+-Win32_System_Com_UI = ["Win32_System_Com"]
+-Win32_System_Com_Urlmon = ["Win32_System_Com"]
+-Win32_System_ComponentServices = ["Win32_System"]
+-Win32_System_Console = ["Win32_System"]
+-Win32_System_Contacts = ["Win32_System"]
+-Win32_System_CorrelationVector = ["Win32_System"]
+-Win32_System_DataExchange = ["Win32_System"]
+-Win32_System_DeploymentServices = ["Win32_System"]
+-Win32_System_DesktopSharing = ["Win32_System"]
+-Win32_System_DeveloperLicensing = ["Win32_System"]
+-Win32_System_Diagnostics = ["Win32_System"]
+-Win32_System_Diagnostics_Ceip = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ClrProfiling = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug_ActiveScript = ["Win32_System_Diagnostics_Debug"]
+-Win32_System_Diagnostics_Debug_Extensions = ["Win32_System_Diagnostics_Debug"]
+-Win32_System_Diagnostics_Etw = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ProcessSnapshotting = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ToolHelp = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_TraceLogging = ["Win32_System_Diagnostics"]
+-Win32_System_DistributedTransactionCoordinator = ["Win32_System"]
+-Win32_System_Environment = ["Win32_System"]
+-Win32_System_ErrorReporting = ["Win32_System"]
+-Win32_System_EventCollector = ["Win32_System"]
+-Win32_System_EventLog = ["Win32_System"]
+-Win32_System_EventNotificationService = ["Win32_System"]
+-Win32_System_GroupPolicy = ["Win32_System"]
+-Win32_System_HostCompute = ["Win32_System"]
+-Win32_System_HostComputeNetwork = ["Win32_System"]
+-Win32_System_HostComputeSystem = ["Win32_System"]
+-Win32_System_Hypervisor = ["Win32_System"]
+-Win32_System_IO = ["Win32_System"]
+-Win32_System_Iis = ["Win32_System"]
+-Win32_System_Ioctl = ["Win32_System"]
+-Win32_System_JobObjects = ["Win32_System"]
+-Win32_System_Js = ["Win32_System"]
+-Win32_System_Kernel = ["Win32_System"]
+-Win32_System_LibraryLoader = ["Win32_System"]
+-Win32_System_Mailslots = ["Win32_System"]
+-Win32_System_Mapi = ["Win32_System"]
+-Win32_System_Memory = ["Win32_System"]
+-Win32_System_Memory_NonVolatile = ["Win32_System_Memory"]
+-Win32_System_MessageQueuing = ["Win32_System"]
+-Win32_System_MixedReality = ["Win32_System"]
+-Win32_System_Mmc = ["Win32_System"]
+-Win32_System_Ole = ["Win32_System"]
+-Win32_System_ParentalControls = ["Win32_System"]
+-Win32_System_PasswordManagement = ["Win32_System"]
+-Win32_System_Performance = ["Win32_System"]
+-Win32_System_Performance_HardwareCounterProfiling = ["Win32_System_Performance"]
+-Win32_System_Pipes = ["Win32_System"]
+-Win32_System_Power = ["Win32_System"]
+-Win32_System_ProcessStatus = ["Win32_System"]
+-Win32_System_RealTimeCommunications = ["Win32_System"]
+-Win32_System_Recovery = ["Win32_System"]
+-Win32_System_Registry = ["Win32_System"]
+-Win32_System_RemoteAssistance = ["Win32_System"]
+-Win32_System_RemoteDesktop = ["Win32_System"]
+-Win32_System_RemoteManagement = ["Win32_System"]
+-Win32_System_RestartManager = ["Win32_System"]
+-Win32_System_Restore = ["Win32_System"]
+-Win32_System_Rpc = ["Win32_System"]
+-Win32_System_Search = ["Win32_System"]
+-Win32_System_Search_Common = ["Win32_System_Search"]
+-Win32_System_SecurityCenter = ["Win32_System"]
+-Win32_System_ServerBackup = ["Win32_System"]
+-Win32_System_Services = ["Win32_System"]
+-Win32_System_SettingsManagementInfrastructure = ["Win32_System"]
+-Win32_System_SetupAndMigration = ["Win32_System"]
+-Win32_System_Shutdown = ["Win32_System"]
+-Win32_System_SideShow = ["Win32_System"]
+-Win32_System_StationsAndDesktops = ["Win32_System"]
+-Win32_System_SubsystemForLinux = ["Win32_System"]
+-Win32_System_SystemInformation = ["Win32_System"]
+-Win32_System_SystemServices = ["Win32_System"]
+-Win32_System_TaskScheduler = ["Win32_System"]
+-Win32_System_Threading = ["Win32_System"]
+-Win32_System_Time = ["Win32_System"]
+-Win32_System_TpmBaseServices = ["Win32_System"]
+-Win32_System_TransactionServer = ["Win32_System"]
+-Win32_System_UpdateAgent = ["Win32_System"]
+-Win32_System_UpdateAssessment = ["Win32_System"]
+-Win32_System_UserAccessLogging = ["Win32_System"]
+-Win32_System_Variant = ["Win32_System"]
+-Win32_System_VirtualDosMachines = ["Win32_System"]
+-Win32_System_WinRT = ["Win32_System"]
+-Win32_System_WinRT_AllJoyn = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Composition = ["Win32_System_WinRT"]
+-Win32_System_WinRT_CoreInputView = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Direct3D11 = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Display = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Graphics = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Graphics_Capture = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Graphics_Direct2D = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Graphics_Imaging = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Holographic = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Isolation = ["Win32_System_WinRT"]
+-Win32_System_WinRT_ML = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Media = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Metadata = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Pdf = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Printing = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Shell = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Storage = ["Win32_System_WinRT"]
+-Win32_System_WindowsProgramming = ["Win32_System"]
+-Win32_System_WindowsSync = ["Win32_System"]
+-Win32_System_Wmi = ["Win32_System"]
+-Win32_UI = ["Win32"]
+-Win32_UI_Accessibility = ["Win32_UI"]
+-Win32_UI_Animation = ["Win32_UI"]
+-Win32_UI_ColorSystem = ["Win32_UI"]
+-Win32_UI_Controls = ["Win32_UI"]
+-Win32_UI_Controls_Dialogs = ["Win32_UI_Controls"]
+-Win32_UI_Controls_RichEdit = ["Win32_UI_Controls"]
+-Win32_UI_HiDpi = ["Win32_UI"]
+-Win32_UI_Input = ["Win32_UI"]
+-Win32_UI_Input_Ime = ["Win32_UI_Input"]
+-Win32_UI_Input_Ink = ["Win32_UI_Input"]
+-Win32_UI_Input_KeyboardAndMouse = ["Win32_UI_Input"]
+-Win32_UI_Input_Pointer = ["Win32_UI_Input"]
+-Win32_UI_Input_Radial = ["Win32_UI_Input"]
+-Win32_UI_Input_Touch = ["Win32_UI_Input"]
+-Win32_UI_Input_XboxController = ["Win32_UI_Input"]
+-Win32_UI_InteractionContext = ["Win32_UI"]
+-Win32_UI_LegacyWindowsEnvironmentFeatures = ["Win32_UI"]
+-Win32_UI_Magnification = ["Win32_UI"]
+-Win32_UI_Notifications = ["Win32_UI"]
+-Win32_UI_Ribbon = ["Win32_UI"]
+-Win32_UI_Shell = ["Win32_UI"]
+-Win32_UI_Shell_Common = ["Win32_UI_Shell"]
+-Win32_UI_Shell_PropertiesSystem = ["Win32_UI_Shell"]
+-Win32_UI_TabletPC = ["Win32_UI"]
+-Win32_UI_TextServices = ["Win32_UI"]
+-Win32_UI_WindowsAndMessaging = ["Win32_UI"]
+-Win32_UI_Wpf = ["Win32_UI"]
+-Win32_Web = ["Win32"]
+-Win32_Web_InternetExplorer = ["Win32_Web"]
++Foundation_Collections = []
++Foundation_Diagnostics = []
++Foundation_Metadata = []
++Foundation_Numerics = []
++Gaming = []
++Gaming_Input = []
++Gaming_Input_Custom = []
++Gaming_Input_ForceFeedback = []
++Gaming_Input_Preview = []
++Gaming_Preview = []
++Gaming_Preview_GamesEnumeration = []
++Gaming_UI = []
++Gaming_XboxLive = []
++Gaming_XboxLive_Storage = []
++Globalization = []
++Globalization_Collation = []
++Globalization_DateTimeFormatting = []
++Globalization_Fonts = []
++Globalization_NumberFormatting = []
++Globalization_PhoneNumberFormatting = []
++Graphics = []
++Graphics_Capture = []
++Graphics_DirectX = []
++Graphics_DirectX_Direct3D11 = []
++Graphics_Display = []
++Graphics_Display_Core = []
++Graphics_Effects = []
++Graphics_Holographic = []
++Graphics_Imaging = []
++Graphics_Printing = []
++Graphics_Printing3D = []
++Graphics_Printing_OptionDetails = []
++Graphics_Printing_PrintSupport = []
++Graphics_Printing_PrintTicket = []
++Graphics_Printing_Workflow = []
++Management = []
++Management_Core = []
++Management_Deployment = []
++Management_Deployment_Preview = []
++Management_Policies = []
++Management_Update = []
++Management_Workplace = []
++Media = []
++Media_AppBroadcasting = []
++Media_AppRecording = []
++Media_Audio = []
++Media_Capture = []
++Media_Capture_Core = []
++Media_Capture_Frames = []
++Media_Casting = []
++Media_ClosedCaptioning = []
++Media_ContentRestrictions = []
++Media_Control = []
++Media_Core = []
++Media_Core_Preview = []
++Media_Devices = []
++Media_Devices_Core = []
++Media_DialProtocol = []
++Media_Editing = []
++Media_Effects = []
++Media_FaceAnalysis = []
++Media_Import = []
++Media_MediaProperties = []
++Media_Miracast = []
++Media_Ocr = []
++Media_PlayTo = []
++Media_Playback = []
++Media_Playlists = []
++Media_Protection = []
++Media_Protection_PlayReady = []
++Media_Render = []
++Media_SpeechRecognition = []
++Media_SpeechSynthesis = []
++Media_Streaming = []
++Media_Streaming_Adaptive = []
++Media_Transcoding = []
++Networking = []
++Networking_BackgroundTransfer = []
++Networking_Connectivity = []
++Networking_NetworkOperators = []
++Networking_Proximity = []
++Networking_PushNotifications = []
++Networking_ServiceDiscovery = []
++Networking_ServiceDiscovery_Dnssd = []
++Networking_Sockets = []
++Networking_Vpn = []
++Networking_XboxLive = []
++Perception = []
++Perception_Automation = []
++Perception_Automation_Core = []
++Perception_People = []
++Perception_Spatial = []
++Perception_Spatial_Preview = []
++Perception_Spatial_Surfaces = []
++Phone = []
++Phone_ApplicationModel = []
++Phone_Devices = []
++Phone_Devices_Notification = []
++Phone_Devices_Power = []
++Phone_Management = []
++Phone_Management_Deployment = []
++Phone_Media = []
++Phone_Media_Devices = []
++Phone_Notification = []
++Phone_Notification_Management = []
++Phone_PersonalInformation = []
++Phone_PersonalInformation_Provisioning = []
++Phone_Speech = []
++Phone_Speech_Recognition = []
++Phone_StartScreen = []
++Phone_System = []
++Phone_System_Power = []
++Phone_System_Profile = []
++Phone_System_UserProfile = []
++Phone_System_UserProfile_GameServices = []
++Phone_System_UserProfile_GameServices_Core = []
++Phone_UI = []
++Phone_UI_Input = []
++Security = []
++Security_Authentication = []
++Security_Authentication_Identity = []
++Security_Authentication_Identity_Core = []
++Security_Authentication_OnlineId = []
++Security_Authentication_Web = []
++Security_Authentication_Web_Core = []
++Security_Authentication_Web_Provider = []
++Security_Authorization = []
++Security_Authorization_AppCapabilityAccess = []
++Security_Credentials = []
++Security_Credentials_UI = []
++Security_Cryptography = []
++Security_Cryptography_Certificates = []
++Security_Cryptography_Core = []
++Security_Cryptography_DataProtection = []
++Security_DataProtection = []
++Security_EnterpriseData = []
++Security_ExchangeActiveSyncProvisioning = []
++Security_Isolation = []
++Services = []
++Services_Maps = []
++Services_Maps_Guidance = []
++Services_Maps_LocalSearch = []
++Services_Maps_OfflineMaps = []
++Services_Store = []
++Services_TargetedContent = []
++Storage = []
++Storage_AccessCache = []
++Storage_BulkAccess = []
++Storage_Compression = []
++Storage_FileProperties = []
++Storage_Pickers = []
++Storage_Pickers_Provider = []
++Storage_Provider = []
++Storage_Search = []
++Storage_Streams = []
++System = []
++System_Diagnostics = []
++System_Diagnostics_DevicePortal = []
++System_Diagnostics_Telemetry = []
++System_Diagnostics_TraceReporting = []
++System_Display = []
++System_Implementation = []
++System_Implementation_FileExplorer = []
++System_Inventory = []
++System_Power = []
++System_Profile = []
++System_Profile_SystemManufacturers = []
++System_RemoteDesktop = []
++System_RemoteDesktop_Input = []
++System_RemoteDesktop_Provider = []
++System_RemoteSystems = []
++System_Threading = []
++System_Threading_Core = []
++System_Update = []
++System_UserProfile = []
++UI = []
++UI_Accessibility = []
++UI_ApplicationSettings = []
++UI_Composition = []
++UI_Composition_Core = []
++UI_Composition_Desktop = []
++UI_Composition_Diagnostics = []
++UI_Composition_Effects = []
++UI_Composition_Interactions = []
++UI_Composition_Scenes = []
++UI_Core = []
++UI_Core_AnimationMetrics = []
++UI_Core_Preview = []
++UI_Input = []
++UI_Input_Core = []
++UI_Input_Inking = []
++UI_Input_Inking_Analysis = []
++UI_Input_Inking_Core = []
++UI_Input_Inking_Preview = []
++UI_Input_Preview = []
++UI_Input_Preview_Injection = []
++UI_Input_Spatial = []
++UI_Notifications = []
++UI_Notifications_Management = []
++UI_Notifications_Preview = []
++UI_Popups = []
++UI_Shell = []
++UI_StartScreen = []
++UI_Text = []
++UI_Text_Core = []
++UI_UIAutomation = []
++UI_UIAutomation_Core = []
++UI_ViewManagement = []
++UI_ViewManagement_Core = []
++UI_WebUI = []
++UI_WebUI_Core = []
++UI_WindowManagement = []
++UI_WindowManagement_Preview = []
++Wdk = []
++Wdk_Devices = []
++Wdk_Devices_HumanInterfaceDevice = []
++Wdk_Foundation = []
++Wdk_Graphics = []
++Wdk_Graphics_Direct3D = []
++Wdk_NetworkManagement = []
++Wdk_NetworkManagement_Ndis = []
++Wdk_NetworkManagement_WindowsFilteringPlatform = []
++Wdk_Storage = []
++Wdk_Storage_FileSystem = []
++Wdk_Storage_FileSystem_Minifilters = []
++Wdk_System = []
++Wdk_System_IO = []
++Wdk_System_OfflineRegistry = []
++Wdk_System_Registry = []
++Wdk_System_SystemInformation = []
++Wdk_System_SystemServices = []
++Wdk_System_Threading = []
++Web = []
++Web_AtomPub = []
++Web_Http = []
++Web_Http_Diagnostics = []
++Web_Http_Filters = []
++Web_Http_Headers = []
++Web_Syndication = []
++Web_UI = []
++Web_UI_Interop = []
++Win32 = []
++Win32_AI = []
++Win32_AI_MachineLearning = []
++Win32_AI_MachineLearning_DirectML = []
++Win32_AI_MachineLearning_WinML = []
++Win32_Data = []
++Win32_Data_HtmlHelp = []
++Win32_Data_RightsManagement = []
++Win32_Data_Xml = []
++Win32_Data_Xml_MsXml = []
++Win32_Data_Xml_XmlLite = []
++Win32_Devices = []
++Win32_Devices_AllJoyn = []
++Win32_Devices_BiometricFramework = []
++Win32_Devices_Bluetooth = []
++Win32_Devices_Communication = []
++Win32_Devices_DeviceAccess = []
++Win32_Devices_DeviceAndDriverInstallation = []
++Win32_Devices_DeviceQuery = []
++Win32_Devices_Display = []
++Win32_Devices_Enumeration = []
++Win32_Devices_Enumeration_Pnp = []
++Win32_Devices_Fax = []
++Win32_Devices_FunctionDiscovery = []
++Win32_Devices_Geolocation = []
++Win32_Devices_HumanInterfaceDevice = []
++Win32_Devices_ImageAcquisition = []
++Win32_Devices_PortableDevices = []
++Win32_Devices_Properties = []
++Win32_Devices_Pwm = []
++Win32_Devices_Sensors = []
++Win32_Devices_SerialCommunication = []
++Win32_Devices_Tapi = []
++Win32_Devices_Usb = []
++Win32_Devices_WebServicesOnDevices = []
++Win32_Foundation = []
++Win32_Gaming = []
++Win32_Globalization = []
++Win32_Graphics = []
++Win32_Graphics_CompositionSwapchain = []
++Win32_Graphics_DXCore = []
++Win32_Graphics_Direct2D = []
++Win32_Graphics_Direct2D_Common = []
++Win32_Graphics_Direct3D = []
++Win32_Graphics_Direct3D10 = []
++Win32_Graphics_Direct3D11 = []
++Win32_Graphics_Direct3D11on12 = []
++Win32_Graphics_Direct3D12 = []
++Win32_Graphics_Direct3D9 = []
++Win32_Graphics_Direct3D9on12 = []
++Win32_Graphics_Direct3D_Dxc = []
++Win32_Graphics_Direct3D_Fxc = []
++Win32_Graphics_DirectComposition = []
++Win32_Graphics_DirectDraw = []
++Win32_Graphics_DirectManipulation = []
++Win32_Graphics_DirectWrite = []
++Win32_Graphics_Dwm = []
++Win32_Graphics_Dxgi = []
++Win32_Graphics_Dxgi_Common = []
++Win32_Graphics_Gdi = []
++Win32_Graphics_GdiPlus = []
++Win32_Graphics_Hlsl = []
++Win32_Graphics_Imaging = []
++Win32_Graphics_Imaging_D2D = []
++Win32_Graphics_OpenGL = []
++Win32_Graphics_Printing = []
++Win32_Graphics_Printing_PrintTicket = []
++Win32_Management = []
++Win32_Management_MobileDeviceManagementRegistration = []
++Win32_Media = []
++Win32_Media_Audio = []
++Win32_Media_Audio_Apo = []
++Win32_Media_Audio_DirectMusic = []
++Win32_Media_Audio_DirectSound = []
++Win32_Media_Audio_Endpoints = []
++Win32_Media_Audio_XAudio2 = []
++Win32_Media_DeviceManager = []
++Win32_Media_DirectShow = []
++Win32_Media_DirectShow_Tv = []
++Win32_Media_DirectShow_Xml = []
++Win32_Media_DxMediaObjects = []
++Win32_Media_KernelStreaming = []
++Win32_Media_LibrarySharingServices = []
++Win32_Media_MediaFoundation = []
++Win32_Media_MediaPlayer = []
++Win32_Media_Multimedia = []
++Win32_Media_PictureAcquisition = []
++Win32_Media_Speech = []
++Win32_Media_Streaming = []
++Win32_Media_WindowsMediaFormat = []
++Win32_NetworkManagement = []
++Win32_NetworkManagement_Dhcp = []
++Win32_NetworkManagement_Dns = []
++Win32_NetworkManagement_InternetConnectionWizard = []
++Win32_NetworkManagement_IpHelper = []
++Win32_NetworkManagement_MobileBroadband = []
++Win32_NetworkManagement_Multicast = []
++Win32_NetworkManagement_Ndis = []
++Win32_NetworkManagement_NetBios = []
++Win32_NetworkManagement_NetManagement = []
++Win32_NetworkManagement_NetShell = []
++Win32_NetworkManagement_NetworkDiagnosticsFramework = []
++Win32_NetworkManagement_NetworkPolicyServer = []
++Win32_NetworkManagement_P2P = []
++Win32_NetworkManagement_QoS = []
++Win32_NetworkManagement_Rras = []
++Win32_NetworkManagement_Snmp = []
++Win32_NetworkManagement_WNet = []
++Win32_NetworkManagement_WebDav = []
++Win32_NetworkManagement_WiFi = []
++Win32_NetworkManagement_WindowsConnectNow = []
++Win32_NetworkManagement_WindowsConnectionManager = []
++Win32_NetworkManagement_WindowsFilteringPlatform = []
++Win32_NetworkManagement_WindowsFirewall = []
++Win32_NetworkManagement_WindowsNetworkVirtualization = []
++Win32_Networking = []
++Win32_Networking_ActiveDirectory = []
++Win32_Networking_BackgroundIntelligentTransferService = []
++Win32_Networking_Clustering = []
++Win32_Networking_HttpServer = []
++Win32_Networking_Ldap = []
++Win32_Networking_NetworkListManager = []
++Win32_Networking_RemoteDifferentialCompression = []
++Win32_Networking_WebSocket = []
++Win32_Networking_WinHttp = []
++Win32_Networking_WinInet = []
++Win32_Networking_WinSock = []
++Win32_Networking_WindowsWebServices = []
++Win32_Security = []
++Win32_Security_AppLocker = []
++Win32_Security_Authentication = []
++Win32_Security_Authentication_Identity = []
++Win32_Security_Authentication_Identity_Provider = []
++Win32_Security_Authorization = []
++Win32_Security_Authorization_UI = []
++Win32_Security_ConfigurationSnapin = []
++Win32_Security_Credentials = []
++Win32_Security_Cryptography = []
++Win32_Security_Cryptography_Catalog = []
++Win32_Security_Cryptography_Certificates = []
++Win32_Security_Cryptography_Sip = []
++Win32_Security_Cryptography_UI = []
++Win32_Security_DiagnosticDataQuery = []
++Win32_Security_DirectoryServices = []
++Win32_Security_EnterpriseData = []
++Win32_Security_ExtensibleAuthenticationProtocol = []
++Win32_Security_Isolation = []
++Win32_Security_LicenseProtection = []
++Win32_Security_NetworkAccessProtection = []
++Win32_Security_Tpm = []
++Win32_Security_WinTrust = []
++Win32_Security_WinWlx = []
++Win32_Storage = []
++Win32_Storage_Cabinets = []
++Win32_Storage_CloudFilters = []
++Win32_Storage_Compression = []
++Win32_Storage_DataDeduplication = []
++Win32_Storage_DistributedFileSystem = []
++Win32_Storage_EnhancedStorage = []
++Win32_Storage_FileHistory = []
++Win32_Storage_FileServerResourceManager = []
++Win32_Storage_FileSystem = []
++Win32_Storage_Imapi = []
++Win32_Storage_IndexServer = []
++Win32_Storage_InstallableFileSystems = []
++Win32_Storage_IscsiDisc = []
++Win32_Storage_Jet = []
++Win32_Storage_Nvme = []
++Win32_Storage_OfflineFiles = []
++Win32_Storage_OperationRecorder = []
++Win32_Storage_Packaging = []
++Win32_Storage_Packaging_Appx = []
++Win32_Storage_Packaging_Opc = []
++Win32_Storage_ProjectedFileSystem = []
++Win32_Storage_StructuredStorage = []
++Win32_Storage_Vhd = []
++Win32_Storage_VirtualDiskService = []
++Win32_Storage_Vss = []
++Win32_Storage_Xps = []
++Win32_Storage_Xps_Printing = []
++Win32_System = []
++Win32_System_AddressBook = []
++Win32_System_Antimalware = []
++Win32_System_ApplicationInstallationAndServicing = []
++Win32_System_ApplicationVerifier = []
++Win32_System_AssessmentTool = []
++Win32_System_ClrHosting = []
++Win32_System_Com = []
++Win32_System_Com_CallObj = []
++Win32_System_Com_ChannelCredentials = []
++Win32_System_Com_Events = []
++Win32_System_Com_Marshal = []
++Win32_System_Com_StructuredStorage = []
++Win32_System_Com_UI = []
++Win32_System_Com_Urlmon = []
++Win32_System_ComponentServices = []
++Win32_System_Console = []
++Win32_System_Contacts = []
++Win32_System_CorrelationVector = []
++Win32_System_DataExchange = []
++Win32_System_DeploymentServices = []
++Win32_System_DesktopSharing = []
++Win32_System_DeveloperLicensing = []
++Win32_System_Diagnostics = []
++Win32_System_Diagnostics_Ceip = []
++Win32_System_Diagnostics_ClrProfiling = []
++Win32_System_Diagnostics_Debug = []
++Win32_System_Diagnostics_Debug_ActiveScript = []
++Win32_System_Diagnostics_Debug_Extensions = []
++Win32_System_Diagnostics_Etw = []
++Win32_System_Diagnostics_ProcessSnapshotting = []
++Win32_System_Diagnostics_ToolHelp = []
++Win32_System_Diagnostics_TraceLogging = []
++Win32_System_DistributedTransactionCoordinator = []
++Win32_System_Environment = []
++Win32_System_ErrorReporting = []
++Win32_System_EventCollector = []
++Win32_System_EventLog = []
++Win32_System_EventNotificationService = []
++Win32_System_GroupPolicy = []
++Win32_System_HostCompute = []
++Win32_System_HostComputeNetwork = []
++Win32_System_HostComputeSystem = []
++Win32_System_Hypervisor = []
++Win32_System_IO = []
++Win32_System_Iis = []
++Win32_System_Ioctl = []
++Win32_System_JobObjects = []
++Win32_System_Js = []
++Win32_System_Kernel = []
++Win32_System_LibraryLoader = []
++Win32_System_Mailslots = []
++Win32_System_Mapi = []
++Win32_System_Memory = []
++Win32_System_Memory_NonVolatile = []
++Win32_System_MessageQueuing = []
++Win32_System_MixedReality = []
++Win32_System_Mmc = []
++Win32_System_Ole = []
++Win32_System_ParentalControls = []
++Win32_System_PasswordManagement = []
++Win32_System_Performance = []
++Win32_System_Performance_HardwareCounterProfiling = []
++Win32_System_Pipes = []
++Win32_System_Power = []
++Win32_System_ProcessStatus = []
++Win32_System_RealTimeCommunications = []
++Win32_System_Recovery = []
++Win32_System_Registry = []
++Win32_System_RemoteAssistance = []
++Win32_System_RemoteDesktop = []
++Win32_System_RemoteManagement = []
++Win32_System_RestartManager = []
++Win32_System_Restore = []
++Win32_System_Rpc = []
++Win32_System_Search = []
++Win32_System_Search_Common = []
++Win32_System_SecurityCenter = []
++Win32_System_ServerBackup = []
++Win32_System_Services = []
++Win32_System_SettingsManagementInfrastructure = []
++Win32_System_SetupAndMigration = []
++Win32_System_Shutdown = []
++Win32_System_SideShow = []
++Win32_System_StationsAndDesktops = []
++Win32_System_SubsystemForLinux = []
++Win32_System_SystemInformation = []
++Win32_System_SystemServices = []
++Win32_System_TaskScheduler = []
++Win32_System_Threading = []
++Win32_System_Time = []
++Win32_System_TpmBaseServices = []
++Win32_System_TransactionServer = []
++Win32_System_UpdateAgent = []
++Win32_System_UpdateAssessment = []
++Win32_System_UserAccessLogging = []
++Win32_System_Variant = []
++Win32_System_VirtualDosMachines = []
++Win32_System_WinRT = []
++Win32_System_WinRT_AllJoyn = []
++Win32_System_WinRT_Composition = []
++Win32_System_WinRT_CoreInputView = []
++Win32_System_WinRT_Direct3D11 = []
++Win32_System_WinRT_Display = []
++Win32_System_WinRT_Graphics = []
++Win32_System_WinRT_Graphics_Capture = []
++Win32_System_WinRT_Graphics_Direct2D = []
++Win32_System_WinRT_Graphics_Imaging = []
++Win32_System_WinRT_Holographic = []
++Win32_System_WinRT_Isolation = []
++Win32_System_WinRT_ML = []
++Win32_System_WinRT_Media = []
++Win32_System_WinRT_Metadata = []
++Win32_System_WinRT_Pdf = []
++Win32_System_WinRT_Printing = []
++Win32_System_WinRT_Shell = []
++Win32_System_WinRT_Storage = []
++Win32_System_WindowsProgramming = []
++Win32_System_WindowsSync = []
++Win32_System_Wmi = []
++Win32_UI = []
++Win32_UI_Accessibility = []
++Win32_UI_Animation = []
++Win32_UI_ColorSystem = []
++Win32_UI_Controls = []
++Win32_UI_Controls_Dialogs = []
++Win32_UI_Controls_RichEdit = []
++Win32_UI_HiDpi = []
++Win32_UI_Input = []
++Win32_UI_Input_Ime = []
++Win32_UI_Input_Ink = []
++Win32_UI_Input_KeyboardAndMouse = []
++Win32_UI_Input_Pointer = []
++Win32_UI_Input_Radial = []
++Win32_UI_Input_Touch = []
++Win32_UI_Input_XboxController = []
++Win32_UI_InteractionContext = []
++Win32_UI_LegacyWindowsEnvironmentFeatures = []
++Win32_UI_Magnification = []
++Win32_UI_Notifications = []
++Win32_UI_Ribbon = []
++Win32_UI_Shell = []
++Win32_UI_Shell_Common = []
++Win32_UI_Shell_PropertiesSystem = []
++Win32_UI_TabletPC = []
++Win32_UI_TextServices = []
++Win32_UI_WindowsAndMessaging = []
++Win32_UI_Wpf = []
++Win32_Web = []
++Win32_Web_InternetExplorer = []
+ default = []
+ deprecated = []
+ docs = []
+ implement = [
+-    "windows-implement",
+-    "windows-interface",
+-    "windows-core/implement",
+ ]
+ [lints.rust]
diff --git a/tests/configs/windows-0.58/debian/patches/series b/tests/configs/windows-0.58/debian/patches/series
new file mode 100644 (file)
index 0000000..20d1cc7
--- /dev/null
@@ -0,0 +1 @@
+remove-cycles.patch
diff --git a/tests/configs/windows-0.58/debian/rules b/tests/configs/windows-0.58/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/windows-0.58/debian/rules.debcargo.hint b/tests/configs/windows-0.58/debian/rules.debcargo.hint
new file mode 100755 (executable)
index 0000000..92c239b
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+
+override_dh_auto_test:
+       dh_auto_test -- test --all
diff --git a/tests/configs/windows-i686-gnullvm-0.52/debian/debcargo.toml b/tests/configs/windows-i686-gnullvm-0.52/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/windows-i686-gnullvm-0.52/debian/rules b/tests/configs/windows-i686-gnullvm-0.52/debian/rules
new file mode 100755 (executable)
index 0000000..6c28854
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_strip:
diff --git a/tests/configs/windows-sys-0.59/debian/changelog b/tests/configs/windows-sys-0.59/debian/changelog
new file mode 100644 (file)
index 0000000..bfc9255
--- /dev/null
@@ -0,0 +1,6 @@
+rust-windows-sys-0.59 (0.59.0-1) UNRELEASED-FIXME-AUTOGENERATED-DEBCARGO; urgency=medium
+
+  * Team upload.
+  * Package windows-sys 0.59.0 from crates.io using debcargo 2.6.1
+
+ -- Fabian Grünbichler <debian@fabian.gruenbichler.email>  Thu, 19 Sep 2024 17:15:57 +0200
diff --git a/tests/configs/windows-sys-0.59/debian/debcargo.toml b/tests/configs/windows-sys-0.59/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..59745d0
--- /dev/null
@@ -0,0 +1,6 @@
+overlay = "."
+
+[packages.lib]
+test_is_broken = false
+[packages."lib+Win32_Foundation"]
+test_is_broken = false
diff --git a/tests/configs/windows-sys-0.59/debian/patches/remove-cycles.patch b/tests/configs/windows-sys-0.59/debian/patches/remove-cycles.patch
new file mode 100644 (file)
index 0000000..80cedec
--- /dev/null
@@ -0,0 +1,491 @@
+Index: rust-windows-sys-0.59.0/Cargo.toml
+===================================================================
+--- rust-windows-sys-0.59.0.orig/Cargo.toml
++++ rust-windows-sys-0.59.0/Cargo.toml
+@@ -42,246 +42,246 @@ doctest = false
+ version = "0.52.6"
+ [features]
+-Wdk = ["Win32_Foundation"]
+-Wdk_Devices = ["Wdk"]
+-Wdk_Devices_Bluetooth = ["Wdk_Devices"]
+-Wdk_Devices_HumanInterfaceDevice = ["Wdk_Devices"]
+-Wdk_Foundation = ["Wdk"]
+-Wdk_Graphics = ["Wdk"]
+-Wdk_Graphics_Direct3D = ["Wdk_Graphics"]
+-Wdk_NetworkManagement = ["Wdk"]
+-Wdk_NetworkManagement_Ndis = ["Wdk_NetworkManagement"]
+-Wdk_NetworkManagement_WindowsFilteringPlatform = ["Wdk_NetworkManagement"]
+-Wdk_Storage = ["Wdk"]
+-Wdk_Storage_FileSystem = ["Wdk_Storage"]
+-Wdk_Storage_FileSystem_Minifilters = ["Wdk_Storage_FileSystem"]
+-Wdk_System = ["Wdk"]
+-Wdk_System_IO = ["Wdk_System"]
+-Wdk_System_Memory = ["Wdk_System"]
+-Wdk_System_OfflineRegistry = ["Wdk_System"]
+-Wdk_System_Registry = ["Wdk_System"]
+-Wdk_System_SystemInformation = ["Wdk_System"]
+-Wdk_System_SystemServices = ["Wdk_System"]
+-Wdk_System_Threading = ["Wdk_System"]
+-Win32 = ["Win32_Foundation"]
+-Win32_Data = ["Win32"]
+-Win32_Data_HtmlHelp = ["Win32_Data"]
+-Win32_Data_RightsManagement = ["Win32_Data"]
+-Win32_Devices = ["Win32"]
+-Win32_Devices_AllJoyn = ["Win32_Devices"]
+-Win32_Devices_BiometricFramework = ["Win32_Devices"]
+-Win32_Devices_Bluetooth = ["Win32_Devices"]
+-Win32_Devices_Communication = ["Win32_Devices"]
+-Win32_Devices_DeviceAndDriverInstallation = ["Win32_Devices"]
+-Win32_Devices_DeviceQuery = ["Win32_Devices"]
+-Win32_Devices_Display = ["Win32_Devices"]
+-Win32_Devices_Enumeration = ["Win32_Devices"]
+-Win32_Devices_Enumeration_Pnp = ["Win32_Devices_Enumeration"]
+-Win32_Devices_Fax = ["Win32_Devices"]
+-Win32_Devices_HumanInterfaceDevice = ["Win32_Devices"]
+-Win32_Devices_PortableDevices = ["Win32_Devices"]
+-Win32_Devices_Properties = ["Win32_Devices"]
+-Win32_Devices_Pwm = ["Win32_Devices"]
+-Win32_Devices_Sensors = ["Win32_Devices"]
+-Win32_Devices_SerialCommunication = ["Win32_Devices"]
+-Win32_Devices_Tapi = ["Win32_Devices"]
+-Win32_Devices_Usb = ["Win32_Devices"]
+-Win32_Devices_WebServicesOnDevices = ["Win32_Devices"]
+-Win32_Foundation = ["Win32"]
+-Win32_Gaming = ["Win32"]
+-Win32_Globalization = ["Win32"]
+-Win32_Graphics = ["Win32"]
+-Win32_Graphics_Dwm = ["Win32_Graphics"]
+-Win32_Graphics_Gdi = ["Win32_Graphics"]
+-Win32_Graphics_GdiPlus = ["Win32_Graphics"]
+-Win32_Graphics_Hlsl = ["Win32_Graphics"]
+-Win32_Graphics_OpenGL = ["Win32_Graphics"]
+-Win32_Graphics_Printing = ["Win32_Graphics"]
+-Win32_Graphics_Printing_PrintTicket = ["Win32_Graphics_Printing"]
+-Win32_Management = ["Win32"]
+-Win32_Management_MobileDeviceManagementRegistration = ["Win32_Management"]
+-Win32_Media = ["Win32"]
+-Win32_Media_Audio = ["Win32_Media"]
+-Win32_Media_DxMediaObjects = ["Win32_Media"]
+-Win32_Media_KernelStreaming = ["Win32_Media"]
+-Win32_Media_Multimedia = ["Win32_Media"]
+-Win32_Media_Streaming = ["Win32_Media"]
+-Win32_Media_WindowsMediaFormat = ["Win32_Media"]
+-Win32_NetworkManagement = ["Win32"]
+-Win32_NetworkManagement_Dhcp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Dns = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_InternetConnectionWizard = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_IpHelper = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Multicast = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Ndis = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetBios = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetManagement = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetShell = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetworkDiagnosticsFramework = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_P2P = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_QoS = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Rras = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Snmp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WNet = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WebDav = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WiFi = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsConnectionManager = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFilteringPlatform = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFirewall = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsNetworkVirtualization = ["Win32_NetworkManagement"]
+-Win32_Networking = ["Win32"]
+-Win32_Networking_ActiveDirectory = ["Win32_Networking"]
+-Win32_Networking_Clustering = ["Win32_Networking"]
+-Win32_Networking_HttpServer = ["Win32_Networking"]
+-Win32_Networking_Ldap = ["Win32_Networking"]
+-Win32_Networking_WebSocket = ["Win32_Networking"]
+-Win32_Networking_WinHttp = ["Win32_Networking"]
+-Win32_Networking_WinInet = ["Win32_Networking"]
+-Win32_Networking_WinSock = ["Win32_Networking"]
+-Win32_Networking_WindowsWebServices = ["Win32_Networking"]
+-Win32_Security = ["Win32"]
+-Win32_Security_AppLocker = ["Win32_Security"]
+-Win32_Security_Authentication = ["Win32_Security"]
+-Win32_Security_Authentication_Identity = ["Win32_Security_Authentication"]
+-Win32_Security_Authorization = ["Win32_Security"]
+-Win32_Security_Credentials = ["Win32_Security"]
+-Win32_Security_Cryptography = ["Win32_Security"]
+-Win32_Security_Cryptography_Catalog = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Certificates = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Sip = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_UI = ["Win32_Security_Cryptography"]
+-Win32_Security_DiagnosticDataQuery = ["Win32_Security"]
+-Win32_Security_DirectoryServices = ["Win32_Security"]
+-Win32_Security_EnterpriseData = ["Win32_Security"]
+-Win32_Security_ExtensibleAuthenticationProtocol = ["Win32_Security"]
+-Win32_Security_Isolation = ["Win32_Security"]
+-Win32_Security_LicenseProtection = ["Win32_Security"]
+-Win32_Security_NetworkAccessProtection = ["Win32_Security"]
+-Win32_Security_WinTrust = ["Win32_Security"]
+-Win32_Security_WinWlx = ["Win32_Security"]
+-Win32_Storage = ["Win32"]
+-Win32_Storage_Cabinets = ["Win32_Storage"]
+-Win32_Storage_CloudFilters = ["Win32_Storage"]
+-Win32_Storage_Compression = ["Win32_Storage"]
+-Win32_Storage_DistributedFileSystem = ["Win32_Storage"]
+-Win32_Storage_FileHistory = ["Win32_Storage"]
+-Win32_Storage_FileSystem = ["Win32_Storage"]
+-Win32_Storage_Imapi = ["Win32_Storage"]
+-Win32_Storage_IndexServer = ["Win32_Storage"]
+-Win32_Storage_InstallableFileSystems = ["Win32_Storage"]
+-Win32_Storage_IscsiDisc = ["Win32_Storage"]
+-Win32_Storage_Jet = ["Win32_Storage"]
+-Win32_Storage_Nvme = ["Win32_Storage"]
+-Win32_Storage_OfflineFiles = ["Win32_Storage"]
+-Win32_Storage_OperationRecorder = ["Win32_Storage"]
+-Win32_Storage_Packaging = ["Win32_Storage"]
+-Win32_Storage_Packaging_Appx = ["Win32_Storage_Packaging"]
+-Win32_Storage_ProjectedFileSystem = ["Win32_Storage"]
+-Win32_Storage_StructuredStorage = ["Win32_Storage"]
+-Win32_Storage_Vhd = ["Win32_Storage"]
+-Win32_Storage_Xps = ["Win32_Storage"]
+-Win32_System = ["Win32"]
+-Win32_System_AddressBook = ["Win32_System"]
+-Win32_System_Antimalware = ["Win32_System"]
+-Win32_System_ApplicationInstallationAndServicing = ["Win32_System"]
+-Win32_System_ApplicationVerifier = ["Win32_System"]
+-Win32_System_ClrHosting = ["Win32_System"]
+-Win32_System_Com = ["Win32_System"]
+-Win32_System_Com_Marshal = ["Win32_System_Com"]
+-Win32_System_Com_StructuredStorage = ["Win32_System_Com"]
+-Win32_System_Com_Urlmon = ["Win32_System_Com"]
+-Win32_System_ComponentServices = ["Win32_System"]
+-Win32_System_Console = ["Win32_System"]
+-Win32_System_CorrelationVector = ["Win32_System"]
+-Win32_System_DataExchange = ["Win32_System"]
+-Win32_System_DeploymentServices = ["Win32_System"]
+-Win32_System_DeveloperLicensing = ["Win32_System"]
+-Win32_System_Diagnostics = ["Win32_System"]
+-Win32_System_Diagnostics_Ceip = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug_Extensions = ["Win32_System_Diagnostics_Debug"]
+-Win32_System_Diagnostics_Etw = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ProcessSnapshotting = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ToolHelp = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_TraceLogging = ["Win32_System_Diagnostics"]
+-Win32_System_DistributedTransactionCoordinator = ["Win32_System"]
+-Win32_System_Environment = ["Win32_System"]
+-Win32_System_ErrorReporting = ["Win32_System"]
+-Win32_System_EventCollector = ["Win32_System"]
+-Win32_System_EventLog = ["Win32_System"]
+-Win32_System_EventNotificationService = ["Win32_System"]
+-Win32_System_GroupPolicy = ["Win32_System"]
+-Win32_System_HostCompute = ["Win32_System"]
+-Win32_System_HostComputeNetwork = ["Win32_System"]
+-Win32_System_HostComputeSystem = ["Win32_System"]
+-Win32_System_Hypervisor = ["Win32_System"]
+-Win32_System_IO = ["Win32_System"]
+-Win32_System_Iis = ["Win32_System"]
+-Win32_System_Ioctl = ["Win32_System"]
+-Win32_System_JobObjects = ["Win32_System"]
+-Win32_System_Js = ["Win32_System"]
+-Win32_System_Kernel = ["Win32_System"]
+-Win32_System_LibraryLoader = ["Win32_System"]
+-Win32_System_Mailslots = ["Win32_System"]
+-Win32_System_Mapi = ["Win32_System"]
+-Win32_System_Memory = ["Win32_System"]
+-Win32_System_Memory_NonVolatile = ["Win32_System_Memory"]
+-Win32_System_MessageQueuing = ["Win32_System"]
+-Win32_System_MixedReality = ["Win32_System"]
+-Win32_System_Ole = ["Win32_System"]
+-Win32_System_PasswordManagement = ["Win32_System"]
+-Win32_System_Performance = ["Win32_System"]
+-Win32_System_Performance_HardwareCounterProfiling = ["Win32_System_Performance"]
+-Win32_System_Pipes = ["Win32_System"]
+-Win32_System_Power = ["Win32_System"]
+-Win32_System_ProcessStatus = ["Win32_System"]
+-Win32_System_Recovery = ["Win32_System"]
+-Win32_System_Registry = ["Win32_System"]
+-Win32_System_RemoteDesktop = ["Win32_System"]
+-Win32_System_RemoteManagement = ["Win32_System"]
+-Win32_System_RestartManager = ["Win32_System"]
+-Win32_System_Restore = ["Win32_System"]
+-Win32_System_Rpc = ["Win32_System"]
+-Win32_System_Search = ["Win32_System"]
+-Win32_System_Search_Common = ["Win32_System_Search"]
+-Win32_System_SecurityCenter = ["Win32_System"]
+-Win32_System_Services = ["Win32_System"]
+-Win32_System_SetupAndMigration = ["Win32_System"]
+-Win32_System_Shutdown = ["Win32_System"]
+-Win32_System_StationsAndDesktops = ["Win32_System"]
+-Win32_System_SubsystemForLinux = ["Win32_System"]
+-Win32_System_SystemInformation = ["Win32_System"]
+-Win32_System_SystemServices = ["Win32_System"]
+-Win32_System_Threading = ["Win32_System"]
+-Win32_System_Time = ["Win32_System"]
+-Win32_System_TpmBaseServices = ["Win32_System"]
+-Win32_System_UserAccessLogging = ["Win32_System"]
+-Win32_System_Variant = ["Win32_System"]
+-Win32_System_VirtualDosMachines = ["Win32_System"]
+-Win32_System_WindowsProgramming = ["Win32_System"]
+-Win32_System_Wmi = ["Win32_System"]
+-Win32_UI = ["Win32"]
+-Win32_UI_Accessibility = ["Win32_UI"]
+-Win32_UI_ColorSystem = ["Win32_UI"]
+-Win32_UI_Controls = ["Win32_UI"]
+-Win32_UI_Controls_Dialogs = ["Win32_UI_Controls"]
+-Win32_UI_HiDpi = ["Win32_UI"]
+-Win32_UI_Input = ["Win32_UI"]
+-Win32_UI_Input_Ime = ["Win32_UI_Input"]
+-Win32_UI_Input_KeyboardAndMouse = ["Win32_UI_Input"]
+-Win32_UI_Input_Pointer = ["Win32_UI_Input"]
+-Win32_UI_Input_Touch = ["Win32_UI_Input"]
+-Win32_UI_Input_XboxController = ["Win32_UI_Input"]
+-Win32_UI_InteractionContext = ["Win32_UI"]
+-Win32_UI_Magnification = ["Win32_UI"]
+-Win32_UI_Shell = ["Win32_UI"]
+-Win32_UI_Shell_Common = ["Win32_UI_Shell"]
+-Win32_UI_Shell_PropertiesSystem = ["Win32_UI_Shell"]
+-Win32_UI_TabletPC = ["Win32_UI"]
+-Win32_UI_TextServices = ["Win32_UI"]
+-Win32_UI_WindowsAndMessaging = ["Win32_UI"]
+-Win32_Web = ["Win32"]
+-Win32_Web_InternetExplorer = ["Win32_Web"]
++Wdk = []
++Wdk_Devices = []
++Wdk_Devices_Bluetooth = []
++Wdk_Devices_HumanInterfaceDevice = []
++Wdk_Foundation = []
++Wdk_Graphics = []
++Wdk_Graphics_Direct3D = []
++Wdk_NetworkManagement = []
++Wdk_NetworkManagement_Ndis = []
++Wdk_NetworkManagement_WindowsFilteringPlatform = []
++Wdk_Storage = []
++Wdk_Storage_FileSystem = []
++Wdk_Storage_FileSystem_Minifilters = []
++Wdk_System = []
++Wdk_System_IO = []
++Wdk_System_Memory = []
++Wdk_System_OfflineRegistry = []
++Wdk_System_Registry = []
++Wdk_System_SystemInformation = []
++Wdk_System_SystemServices = []
++Wdk_System_Threading = []
++Win32 = []
++Win32_Data = []
++Win32_Data_HtmlHelp = []
++Win32_Data_RightsManagement = []
++Win32_Devices = []
++Win32_Devices_AllJoyn = []
++Win32_Devices_BiometricFramework = []
++Win32_Devices_Bluetooth = []
++Win32_Devices_Communication = []
++Win32_Devices_DeviceAndDriverInstallation = []
++Win32_Devices_DeviceQuery = []
++Win32_Devices_Display = []
++Win32_Devices_Enumeration = []
++Win32_Devices_Enumeration_Pnp = []
++Win32_Devices_Fax = []
++Win32_Devices_HumanInterfaceDevice = []
++Win32_Devices_PortableDevices = []
++Win32_Devices_Properties = []
++Win32_Devices_Pwm = []
++Win32_Devices_Sensors = []
++Win32_Devices_SerialCommunication = []
++Win32_Devices_Tapi = []
++Win32_Devices_Usb = []
++Win32_Devices_WebServicesOnDevices = []
++Win32_Foundation = []
++Win32_Gaming = []
++Win32_Globalization = []
++Win32_Graphics = []
++Win32_Graphics_Dwm = []
++Win32_Graphics_Gdi = []
++Win32_Graphics_GdiPlus = []
++Win32_Graphics_Hlsl = []
++Win32_Graphics_OpenGL = []
++Win32_Graphics_Printing = []
++Win32_Graphics_Printing_PrintTicket = []
++Win32_Management = []
++Win32_Management_MobileDeviceManagementRegistration = []
++Win32_Media = []
++Win32_Media_Audio = []
++Win32_Media_DxMediaObjects = []
++Win32_Media_KernelStreaming = []
++Win32_Media_Multimedia = []
++Win32_Media_Streaming = []
++Win32_Media_WindowsMediaFormat = []
++Win32_NetworkManagement = []
++Win32_NetworkManagement_Dhcp = []
++Win32_NetworkManagement_Dns = []
++Win32_NetworkManagement_InternetConnectionWizard = []
++Win32_NetworkManagement_IpHelper = []
++Win32_NetworkManagement_Multicast = []
++Win32_NetworkManagement_Ndis = []
++Win32_NetworkManagement_NetBios = []
++Win32_NetworkManagement_NetManagement = []
++Win32_NetworkManagement_NetShell = []
++Win32_NetworkManagement_NetworkDiagnosticsFramework = []
++Win32_NetworkManagement_P2P = []
++Win32_NetworkManagement_QoS = []
++Win32_NetworkManagement_Rras = []
++Win32_NetworkManagement_Snmp = []
++Win32_NetworkManagement_WNet = []
++Win32_NetworkManagement_WebDav = []
++Win32_NetworkManagement_WiFi = []
++Win32_NetworkManagement_WindowsConnectionManager = []
++Win32_NetworkManagement_WindowsFilteringPlatform = []
++Win32_NetworkManagement_WindowsFirewall = []
++Win32_NetworkManagement_WindowsNetworkVirtualization = []
++Win32_Networking = []
++Win32_Networking_ActiveDirectory = []
++Win32_Networking_Clustering = []
++Win32_Networking_HttpServer = []
++Win32_Networking_Ldap = []
++Win32_Networking_WebSocket = []
++Win32_Networking_WinHttp = []
++Win32_Networking_WinInet = []
++Win32_Networking_WinSock = []
++Win32_Networking_WindowsWebServices = []
++Win32_Security = []
++Win32_Security_AppLocker = []
++Win32_Security_Authentication = []
++Win32_Security_Authentication_Identity = []
++Win32_Security_Authorization = []
++Win32_Security_Credentials = []
++Win32_Security_Cryptography = []
++Win32_Security_Cryptography_Catalog = []
++Win32_Security_Cryptography_Certificates = []
++Win32_Security_Cryptography_Sip = []
++Win32_Security_Cryptography_UI = []
++Win32_Security_DiagnosticDataQuery = []
++Win32_Security_DirectoryServices = []
++Win32_Security_EnterpriseData = []
++Win32_Security_ExtensibleAuthenticationProtocol = []
++Win32_Security_Isolation = []
++Win32_Security_LicenseProtection = []
++Win32_Security_NetworkAccessProtection = []
++Win32_Security_WinTrust = []
++Win32_Security_WinWlx = []
++Win32_Storage = []
++Win32_Storage_Cabinets = []
++Win32_Storage_CloudFilters = []
++Win32_Storage_Compression = []
++Win32_Storage_DistributedFileSystem = []
++Win32_Storage_FileHistory = []
++Win32_Storage_FileSystem = []
++Win32_Storage_Imapi = []
++Win32_Storage_IndexServer = []
++Win32_Storage_InstallableFileSystems = []
++Win32_Storage_IscsiDisc = []
++Win32_Storage_Jet = []
++Win32_Storage_Nvme = []
++Win32_Storage_OfflineFiles = []
++Win32_Storage_OperationRecorder = []
++Win32_Storage_Packaging = []
++Win32_Storage_Packaging_Appx = []
++Win32_Storage_ProjectedFileSystem = []
++Win32_Storage_StructuredStorage = []
++Win32_Storage_Vhd = []
++Win32_Storage_Xps = []
++Win32_System = []
++Win32_System_AddressBook = []
++Win32_System_Antimalware = []
++Win32_System_ApplicationInstallationAndServicing = []
++Win32_System_ApplicationVerifier = []
++Win32_System_ClrHosting = []
++Win32_System_Com = []
++Win32_System_Com_Marshal = []
++Win32_System_Com_StructuredStorage = []
++Win32_System_Com_Urlmon = []
++Win32_System_ComponentServices = []
++Win32_System_Console = []
++Win32_System_CorrelationVector = []
++Win32_System_DataExchange = []
++Win32_System_DeploymentServices = []
++Win32_System_DeveloperLicensing = []
++Win32_System_Diagnostics = []
++Win32_System_Diagnostics_Ceip = []
++Win32_System_Diagnostics_Debug = []
++Win32_System_Diagnostics_Debug_Extensions = []
++Win32_System_Diagnostics_Etw = []
++Win32_System_Diagnostics_ProcessSnapshotting = []
++Win32_System_Diagnostics_ToolHelp = []
++Win32_System_Diagnostics_TraceLogging = []
++Win32_System_DistributedTransactionCoordinator = []
++Win32_System_Environment = []
++Win32_System_ErrorReporting = []
++Win32_System_EventCollector = []
++Win32_System_EventLog = []
++Win32_System_EventNotificationService = []
++Win32_System_GroupPolicy = []
++Win32_System_HostCompute = []
++Win32_System_HostComputeNetwork = []
++Win32_System_HostComputeSystem = []
++Win32_System_Hypervisor = []
++Win32_System_IO = []
++Win32_System_Iis = []
++Win32_System_Ioctl = []
++Win32_System_JobObjects = []
++Win32_System_Js = []
++Win32_System_Kernel = []
++Win32_System_LibraryLoader = []
++Win32_System_Mailslots = []
++Win32_System_Mapi = []
++Win32_System_Memory = []
++Win32_System_Memory_NonVolatile = []
++Win32_System_MessageQueuing = []
++Win32_System_MixedReality = []
++Win32_System_Ole = []
++Win32_System_PasswordManagement = []
++Win32_System_Performance = []
++Win32_System_Performance_HardwareCounterProfiling = []
++Win32_System_Pipes = []
++Win32_System_Power = []
++Win32_System_ProcessStatus = []
++Win32_System_Recovery = []
++Win32_System_Registry = []
++Win32_System_RemoteDesktop = []
++Win32_System_RemoteManagement = []
++Win32_System_RestartManager = []
++Win32_System_Restore = []
++Win32_System_Rpc = []
++Win32_System_Search = []
++Win32_System_Search_Common = []
++Win32_System_SecurityCenter = []
++Win32_System_Services = []
++Win32_System_SetupAndMigration = []
++Win32_System_Shutdown = []
++Win32_System_StationsAndDesktops = []
++Win32_System_SubsystemForLinux = []
++Win32_System_SystemInformation = []
++Win32_System_SystemServices = []
++Win32_System_Threading = []
++Win32_System_Time = []
++Win32_System_TpmBaseServices = []
++Win32_System_UserAccessLogging = []
++Win32_System_Variant = []
++Win32_System_VirtualDosMachines = []
++Win32_System_WindowsProgramming = []
++Win32_System_Wmi = []
++Win32_UI = []
++Win32_UI_Accessibility = []
++Win32_UI_ColorSystem = []
++Win32_UI_Controls = []
++Win32_UI_Controls_Dialogs = []
++Win32_UI_HiDpi = []
++Win32_UI_Input = []
++Win32_UI_Input_Ime = []
++Win32_UI_Input_KeyboardAndMouse = []
++Win32_UI_Input_Pointer = []
++Win32_UI_Input_Touch = []
++Win32_UI_Input_XboxController = []
++Win32_UI_InteractionContext = []
++Win32_UI_Magnification = []
++Win32_UI_Shell = []
++Win32_UI_Shell_Common = []
++Win32_UI_Shell_PropertiesSystem = []
++Win32_UI_TabletPC = []
++Win32_UI_TextServices = []
++Win32_UI_WindowsAndMessaging = []
++Win32_Web = []
++Win32_Web_InternetExplorer = []
+ default = []
+ docs = []
diff --git a/tests/configs/windows-sys-0.59/debian/patches/series b/tests/configs/windows-sys-0.59/debian/patches/series
new file mode 100644 (file)
index 0000000..20d1cc7
--- /dev/null
@@ -0,0 +1 @@
+remove-cycles.patch
diff --git a/tests/configs/windows-sys-0.59/debian/rules b/tests/configs/windows-sys-0.59/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/windows-sys-0.59/debian/rules.debcargo.hint b/tests/configs/windows-sys-0.59/debian/rules.debcargo.hint
new file mode 100755 (executable)
index 0000000..92c239b
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+
+override_dh_auto_test:
+       dh_auto_test -- test --all
diff --git a/tests/configs/windows-x86-64-gnullvm-0.42/debian/debcargo.toml b/tests/configs/windows-x86-64-gnullvm-0.42/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/windows-x86-64-gnullvm-0.42/debian/rules b/tests/configs/windows-x86-64-gnullvm-0.42/debian/rules
new file mode 100755 (executable)
index 0000000..6c28854
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_strip:
diff --git a/tests/configs/windows-x86-64-gnullvm-0.48/debian/debcargo.toml b/tests/configs/windows-x86-64-gnullvm-0.48/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/windows-x86-64-gnullvm-0.48/debian/rules b/tests/configs/windows-x86-64-gnullvm-0.48/debian/rules
new file mode 100755 (executable)
index 0000000..6c28854
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_strip:
diff --git a/tests/configs/windows-x86-64-gnullvm-0.52/debian/debcargo.toml b/tests/configs/windows-x86-64-gnullvm-0.52/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/windows-x86-64-gnullvm-0.52/debian/rules b/tests/configs/windows-x86-64-gnullvm-0.52/debian/rules
new file mode 100755 (executable)
index 0000000..6c28854
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_strip:
diff --git a/tests/configs/winreg-0.10/debian/debcargo.toml b/tests/configs/winreg-0.10/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/winreg-0.10/debian/rules b/tests/configs/winreg-0.10/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/winreg-0.50/debian/debcargo.toml b/tests/configs/winreg-0.50/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/winreg-0.50/debian/rules b/tests/configs/winreg-0.50/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/winreg-0.6/debian/debcargo.toml b/tests/configs/winreg-0.6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/winreg-0.6/debian/rules b/tests/configs/winreg-0.6/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/x86-0.33/debian/debcargo.toml b/tests/configs/x86-0.33/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/x86-0.33/debian/rules b/tests/configs/x86-0.33/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/yeslogic-fontconfig-sys-6/debian/debcargo.toml b/tests/configs/yeslogic-fontconfig-sys-6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..6f7b4cf
--- /dev/null
@@ -0,0 +1,5 @@
+overlay = "."
+semver_suffix = true
+
+[packages.lib]
+depends = ["libfontconfig-dev"]
diff --git a/tests/configs/zip-0.5/debian/debcargo.toml b/tests/configs/zip-0.5/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..66c76f8
--- /dev/null
@@ -0,0 +1,3 @@
+semver_suffix = true
+# tests purposefully contain invalid data that debian tools try to process
+excludes = ["tests/**"]
diff --git a/tests/configs/zip-0.6/debian/debcargo.toml b/tests/configs/zip-0.6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..66c76f8
--- /dev/null
@@ -0,0 +1,3 @@
+semver_suffix = true
+# tests purposefully contain invalid data that debian tools try to process
+excludes = ["tests/**"]
diff --git a/tests/configs/zip/debian/debcargo.toml b/tests/configs/zip/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..66c76f8
--- /dev/null
@@ -0,0 +1,3 @@
+semver_suffix = true
+# tests purposefully contain invalid data that debian tools try to process
+excludes = ["tests/**"]
diff --git a/tests/debcargo_override.toml b/tests/debcargo_override.toml
new file mode 100644 (file)
index 0000000..04e0c69
--- /dev/null
@@ -0,0 +1,20 @@
+uploaders = ["Sylvestre Ledru <sylvestre@debian.org>", "Ximin Luo <infinity0@debian.org>" ]
+
+[source]
+section = "rust"
+build_depends = ["libssl-dev"]
+homepage = "https://salsa.debian.org/rust-team/debcargo-conf"
+
+[packages.bin]
+summary = "Tool to create Debian package from Rust crate"
+description = """
+This package provides debcargo a tool to create Debian source package from Rust
+crate. The package created by this tool is as per the packaging policy set by
+Debian Rust team.
+"""
+
+[packages."extra+libblake3-0"]
+architecture = ["any"]
+section = "libs"
+depends = ["${misc:Depends}", "${shlibs:Depends}"]
+description = "BLAKE3 hash function - C library"
diff --git a/tests/debcargo_override_top_level.toml b/tests/debcargo_override_top_level.toml
new file mode 100644 (file)
index 0000000..13d0d95
--- /dev/null
@@ -0,0 +1,13 @@
+uploaders = ["Sylvestre Ledru <sylvestre@debian.org>", "Ximin Luo <infinity0@debian.org>" ]
+
+summary = "Tool to create Debian package from Rust crate"
+description = """
+This package provides debcargo a tool to create Debian source package from Rust
+crate. The package created by this tool is as per the packaging policy set by
+Debian Rust team.
+"""
+
+[source]
+section = "rust"
+build_depends = ["libssl-dev"]
+homepage = "https://salsa.debian.org/rust-team/debcargo-conf"
diff --git a/tests/foobar-overlay/debian/debcargo.toml b/tests/foobar-overlay/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..9b982f8
--- /dev/null
@@ -0,0 +1,14 @@
+overlay = "."
+crate_src_path = "../../foobar"
+
+[source]
+build_depends = ["some-build-dependency"]
+
+[packages.lib]
+depends = ["some-dependency-for-lib"]
+conflicts = ["global-conflict"]
+
+[packages."lib+somefeature"]
+depends = ["some-dependency-for-lib-with-feature"]
+breaks = ["broken-by-somefeature"]
+replaces = ["replaced-by-somefeature"]
diff --git a/tests/foobar-semver-overlay/debian/debcargo.toml b/tests/foobar-semver-overlay/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..f3d8499
--- /dev/null
@@ -0,0 +1,19 @@
+overlay = "."
+crate_src_path = "../../foobar-semver"
+semver_suffix = true
+requires_root = "no"
+
+[source]
+build_depends = ["some-build-dependency"]
+skip_nocheck = true
+
+[packages.lib]
+depends = ["some-dependency-for-lib"]
+breaks = ["broken-by-everything"]
+replaces = ["replaced-by-everything"]
+conflicts = ["global-conflict"]
+
+[packages."lib+somefeature"]
+depends = ["some-dependency-for-lib-with-feature"]
+breaks = ["broken-by-somefeature"]
+replaces = ["replaced-by-somefeature"]
diff --git a/tests/foobar-semver.expected b/tests/foobar-semver.expected
new file mode 100644 (file)
index 0000000..8d5c535
--- /dev/null
@@ -0,0 +1,94 @@
+Source: rust-foobar-semver-0.1
+Section: rust
+Build-Depends: debhelper-compat (= 13),
+ dh-sequence-cargo,
+ some-build-dependency
+Build-Depends-Arch: cargo:native,
+ rustc:native,
+ libstd-rust-dev,
+ librust-anyhow-1+default-dev (>= 1.0.96),
+ some-dependency-for-lib
+Maintainer: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+Standards-Version: 4.7.3
+Vcs-Git: https://salsa.debian.org/rust-team/debcargo-conf.git [src/foobar-semver-0.1]
+Vcs-Browser: https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/foobar-semver-0.1
+X-Cargo-Crate: foobar-semver
+X-Cargo-Crate-Version: 0.1.0
+Rules-Requires-Root: no
+
+Package: librust-foobar-semver-0.1-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-anyhow-1+default-dev (>= 1.0.96),
+ some-dependency-for-lib
+Suggests:
+ librust-foobar-semver-0.1+futures-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1+somefeature-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1+someotherfeature-dev (= ${binary:Version})
+Provides:
+ librust-foobar-semver-0-dev (= ${binary:Version}),
+ librust-foobar-semver-0+default-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1+default-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1.0-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1.0+default-dev (= ${binary:Version})
+Replaces:
+ librust-foobar-semver-dev (<< 0.1.1~),
+ replaced-by-everything
+Breaks:
+ librust-foobar-semver-dev (<< 0.1.1~),
+ broken-by-everything
+Conflicts:
+ global-conflict
+Description: Rust crate "foobar-semver" - Rust source code
+ Source code for Debianized Rust crate "foobar-semver"
+
+Package: librust-foobar-semver-0.1+futures-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-foobar-semver-0.1-dev (= ${binary:Version}),
+ librust-futures+default-dev (<< 0.4),
+ librust-futures+default-dev (>= 0.2)
+Provides:
+ librust-foobar-semver-0+futures-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1.0+futures-dev (= ${binary:Version})
+Description: Rust crate "foobar-semver" - feature "futures"
+ This metapackage enables feature "futures" for the Rust foobar-semver crate, by
+ pulling in any additional dependencies needed by that feature.
+
+Package: librust-foobar-semver-0.1+somefeature-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-foobar-semver-0.1-dev (= ${binary:Version}),
+ librust-thiserror-2-dev,
+ some-dependency-for-lib-with-feature
+Provides:
+ librust-foobar-semver-0+somefeature-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1.0+somefeature-dev (= ${binary:Version})
+Replaces:
+ replaced-by-somefeature
+Breaks:
+ broken-by-somefeature
+Description: Rust crate "foobar-semver" - feature "somefeature"
+ This metapackage enables feature "somefeature" for the Rust foobar-semver
+ crate, by pulling in any additional dependencies needed by that feature.
+
+Package: librust-foobar-semver-0.1+someotherfeature-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-foobar-semver-0.1-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1+somefeature-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1+futures-dev (= ${binary:Version})
+Provides:
+ librust-foobar-semver-0+someotherfeature-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1.0+someotherfeature-dev (= ${binary:Version})
+Description: Rust crate "foobar-semver" - feature "someotherfeature"
+ This metapackage enables feature "someotherfeature" for the Rust foobar-semver
+ crate, by pulling in any additional dependencies needed by that feature.
diff --git a/tests/foobar.expected b/tests/foobar.expected
new file mode 100644 (file)
index 0000000..5adfa3e
--- /dev/null
@@ -0,0 +1,92 @@
+Source: rust-foobar
+Section: rust
+Build-Depends: debhelper-compat (= 13),
+ dh-sequence-cargo,
+ some-build-dependency
+Build-Depends-Arch: cargo:native <!nocheck>,
+ rustc:native <!nocheck>,
+ libstd-rust-dev <!nocheck>,
+ librust-anyhow-1+default-dev (>= 1.0.96) <!nocheck>,
+ some-dependency-for-lib <!nocheck>
+Maintainer: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+Standards-Version: 4.7.3
+Vcs-Git: https://salsa.debian.org/rust-team/debcargo-conf.git [src/foobar]
+Vcs-Browser: https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/foobar
+X-Cargo-Crate: foobar
+X-Cargo-Crate-Version: 0.1.0
+
+Package: librust-foobar-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-anyhow-1+default-dev (>= 1.0.96),
+ some-dependency-for-lib
+Suggests:
+ librust-foobar+futures-dev (= ${binary:Version}),
+ librust-foobar+somefeature-dev (= ${binary:Version}),
+ librust-foobar+someotherfeature-dev (= ${binary:Version})
+Provides:
+ librust-foobar+default-dev (= ${binary:Version}),
+ librust-foobar-0-dev (= ${binary:Version}),
+ librust-foobar-0+default-dev (= ${binary:Version}),
+ librust-foobar-0.1-dev (= ${binary:Version}),
+ librust-foobar-0.1+default-dev (= ${binary:Version}),
+ librust-foobar-0.1.0-dev (= ${binary:Version}),
+ librust-foobar-0.1.0+default-dev (= ${binary:Version})
+Conflicts:
+ global-conflict
+Description: Rust crate "foobar" - Rust source code
+ Source code for Debianized Rust crate "foobar"
+
+Package: librust-foobar+futures-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-foobar-dev (= ${binary:Version}),
+ librust-futures+default-dev (<< 0.4),
+ librust-futures+default-dev (>= 0.2)
+Provides:
+ librust-foobar-0+futures-dev (= ${binary:Version}),
+ librust-foobar-0.1+futures-dev (= ${binary:Version}),
+ librust-foobar-0.1.0+futures-dev (= ${binary:Version})
+Description: Rust crate "foobar" - feature "futures"
+ This metapackage enables feature "futures" for the Rust foobar crate, by
+ pulling in any additional dependencies needed by that feature.
+
+Package: librust-foobar+somefeature-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-foobar-dev (= ${binary:Version}),
+ librust-thiserror-2-dev,
+ some-dependency-for-lib-with-feature
+Provides:
+ librust-foobar-0+somefeature-dev (= ${binary:Version}),
+ librust-foobar-0.1+somefeature-dev (= ${binary:Version}),
+ librust-foobar-0.1.0+somefeature-dev (= ${binary:Version})
+Replaces:
+ replaced-by-somefeature
+Breaks:
+ broken-by-somefeature
+Description: Rust crate "foobar" - feature "somefeature"
+ This metapackage enables feature "somefeature" for the Rust foobar crate, by
+ pulling in any additional dependencies needed by that feature.
+
+Package: librust-foobar+someotherfeature-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-foobar-dev (= ${binary:Version}),
+ librust-foobar+somefeature-dev (= ${binary:Version}),
+ librust-foobar+futures-dev (= ${binary:Version})
+Provides:
+ librust-foobar-0+someotherfeature-dev (= ${binary:Version}),
+ librust-foobar-0.1+someotherfeature-dev (= ${binary:Version}),
+ librust-foobar-0.1.0+someotherfeature-dev (= ${binary:Version})
+Description: Rust crate "foobar" - feature "someotherfeature"
+ This metapackage enables feature "someotherfeature" for the Rust foobar crate,
+ by pulling in any additional dependencies needed by that feature.
diff --git a/tests/local-crate.rs b/tests/local-crate.rs
new file mode 100644 (file)
index 0000000..c2b2e0e
--- /dev/null
@@ -0,0 +1,59 @@
+extern crate debcargo;
+
+use std::path::Path;
+
+fn local_package_test(tmpdir: &Path, crate_name: &str, version: &str) -> Option<String> {
+    let tempdir = tempfile::Builder::new()
+        .prefix("debcargo")
+        .tempdir_in(tmpdir)
+        .expect("Should be able to create temporary directory");
+    let manifest_dir = env!("CARGO_MANIFEST_DIR");
+    let crate_dir = Path::new(manifest_dir).join("tests").join(crate_name);
+    if !crate_dir.exists() {
+        return None;
+    }
+    let output = std::process::Command::new(env!("CARGO_BIN_EXE_debcargo"))
+        .env("DEBFULLNAME", "Debcargo Test")
+        .env("DEBEMAIL", "debcargo@example.com")
+        .arg("package")
+        .arg("--config")
+        .arg(format!(
+            "{manifest_dir}/tests/{crate_name}-overlay/debian/debcargo.toml"
+        ))
+        .arg("--directory")
+        .arg(tempdir.path().join("output"))
+        .arg("--no-overlay-write-back")
+        .arg(crate_name)
+        .arg(version)
+        .output()
+        .expect("Should be able to run `debcargo package`");
+
+    assert!(output.status.success());
+
+    Some(
+        std::fs::read_to_string(tempdir.path().join("output/debian/control"))
+            .expect("Should be able to read generated debian/control file"),
+    )
+}
+
+#[test]
+fn generate_package_with_crate_src() {
+    let out_dir = Path::new(env!("CARGO_TARGET_TMPDIR"));
+    if let Some(actual) = local_package_test(&out_dir, "foobar", "0.1.0") {
+        std::fs::write(out_dir.join("foobar.actual"), &actual)
+            .expect("Should be able to write out generate control contents");
+        let expected = include_str!("foobar.expected");
+        assert_eq!(actual, expected);
+    }
+}
+
+#[test]
+fn generate_package_with_semver_crate_src() {
+    let out_dir = Path::new(env!("CARGO_TARGET_TMPDIR"));
+    if let Some(actual) = local_package_test(&out_dir, "foobar-semver", "0.1.0") {
+        std::fs::write(out_dir.join("foobar-semver.actual"), &actual)
+            .expect("Should be able to write out generate control contents");
+        let expected = include_str!("foobar-semver.expected");
+        assert_eq!(actual, expected);
+    }
+}
diff --git a/tests/manpages.rs b/tests/manpages.rs
new file mode 100644 (file)
index 0000000..03c2031
--- /dev/null
@@ -0,0 +1,69 @@
+#![cfg(feature = "update-dependencies")]
+
+use clap::CommandFactory;
+use clap_mangen::generate_to;
+use std::{fs, path::PathBuf};
+
+use debcargo::cli::Cli;
+
+#[test]
+fn check_manpages() {
+    let outdir = PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join("manpages");
+    let manpages_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("manpages");
+
+    fs::remove_dir_all(&outdir).ok();
+    fs::create_dir_all(&outdir)
+        .unwrap_or_else(|e| panic!("Could not create temporary manpages directory: {e}"));
+
+    // Generate manpages from scratch
+    generate_to(Cli::command().flatten_help(true), &outdir)
+        .unwrap_or_else(|e| panic!("Could not generate temporary manpages: {e}"));
+
+    // For each generated manpage, check that it exists with the same content in the source directory
+    let changed_manpages: Vec<String> = fs::read_dir(&outdir)
+        .unwrap_or_else(|e| panic!("Could not read temporary manpages directory: {e}"))
+        .filter(|manpage| {
+            let new_manpage = manpage.as_ref().unwrap().path();
+            let old_manpage = manpages_dir.join(new_manpage.file_name().unwrap());
+            if !old_manpage.exists() {
+                true
+            } else {
+                let old_manpage_content = fs::read_to_string(&old_manpage).unwrap_or_else(|e| {
+                    panic!("Could not read {}: {e}", old_manpage.to_string_lossy())
+                });
+                let new_manpage_content = fs::read_to_string(&new_manpage).unwrap_or_else(|e| {
+                    panic!("Could not read {}: {e}", new_manpage.to_string_lossy())
+                });
+                old_manpage_content != new_manpage_content
+            }
+        })
+        .map(|manpage| manpage.unwrap().file_name().to_string_lossy().to_string())
+        .collect();
+
+    // For each manpage in the source directory, check that the generated one exists (i.e. whether
+    // it should be removed)
+    let removed_manpages: Vec<String> = fs::read_dir(&manpages_dir)
+        .unwrap()
+        .filter(|manpage| {
+            !outdir
+                .join(manpage.as_ref().unwrap().path().file_name().unwrap())
+                .exists()
+        })
+        .map(|manpage| manpage.unwrap().file_name().to_string_lossy().to_string())
+        .collect();
+
+    if !(changed_manpages.is_empty() && removed_manpages.is_empty()) {
+        let mut panic_string = vec![String::from("Manpages have changed!")];
+        if !changed_manpages.is_empty() {
+            panic_string.push(format!(
+                "- Please replace {} (new manpages generated in {})",
+                changed_manpages.join(", "),
+                outdir.to_string_lossy()
+            ));
+        }
+        if !removed_manpages.is_empty() {
+            panic_string.push(format!("- Please delete {}", removed_manpages.join(", "),));
+        }
+        panic!("{}", panic_string.join("\n"));
+    }
+}
diff --git a/tests/sh/integrate.sh b/tests/sh/integrate.sh
new file mode 100755 (executable)
index 0000000..0857022
--- /dev/null
@@ -0,0 +1,288 @@
+#!/bin/bash
+set -e
+
+scriptdir="$(dirname "$0")"
+
+# outputs
+directory=tmp
+failures_file=""
+# inputs
+allow_failures="$scriptdir/build-allow-fail"
+lintian_suppress_tags="$scriptdir/lintian-suppress-tags"
+config_dir="$scriptdir/../configs"
+# tweaks
+run_lintian=true
+run_sbuild=false
+keepfiles=false
+resolve=
+extraargs=
+
+export DEBCARGO_TESTING_IGNORE_DEBIAN_POLICY_VIOLATION=1
+export DEBCARGO_TESTING_RUZT=1
+
+export DEB_HOST_ARCH=${DEB_HOST_ARCH:-$(dpkg-architecture -qDEB_HOST_ARCH)}
+
+while getopts 'd:f:a:l:c:bkrRux:zh?' o; do
+       case $o in
+       d ) directory=$OPTARG;;
+       f ) failures_file=$OPTARG;;
+
+       a ) allow_failures=$OPTARG;;
+       c ) config_dir=$OPTARG;;
+
+       b ) run_sbuild=true;;
+       k ) keepfiles=true;;
+       r ) resolve=SourceForDebianUnstable;;
+       R ) resolve=BinaryAllForDebianTesting;;
+       x ) extraargs="$extraargs $OPTARG";;
+       h|\? ) cat >&2 <<eof
+Usage: $0 [-ru] (<crate name>|<path/to/crate>) [..]
+
+Run debcargo, do a source-only build, and call lintian on the results.
+
+  -h            This help text.
+
+Options for output:
+  -d DIR        Output directory, default: $directory. Warning: this will be
+                wiped at the start of the test!
+  -f FILE       File to output failed crates in, instead of exiting non-zero.
+                Relative paths are taken relative to the output directory.
+
+Options for input:
+  -a FILE       File that lists crate names to ignore failures for, default:
+                $allow_failures.
+  -c DIR        Path to config directory, default: $config_dir.
+
+Options to control running:
+  -b            Run sbuild on the resulting dsc package.
+  -k            Don't wipe the output directory at the start of the test, and
+                don't rebuild a crate if its directory already exists.
+  -r            Operate on all transitive build-dependencies of the source
+                package, needed for entry into Debian Unstable.
+  -R            Operate on all transitive dependencies of the binary packages,
+                needed for entry into Debian Testing.
+  -x ARG        Give ARG as an extra argument to debcargo, e.g. like
+                -x--copyright-guess-harder.
+eof
+               exit 2;;
+       esac
+done
+shift $(expr $OPTIND - 1)
+
+allow_fail() {
+       local crate="$1"
+       local version="$2"
+       if ! test -f "${allow_failures}"; then
+               return 1
+       elif grep -qx "${crate}" "${allow_failures}"; then
+               echo >&2 "Allowing ${crate} to fail..."
+               return 0
+       elif [ -n "$version" ] && grep -qx "${crate}-${version}" "${allow_failures}"; then
+               echo >&2 "Allowing ${crate}-${version} to fail..."
+               return 0
+       else
+               return 1
+       fi
+}
+
+shouldbuild() {
+       local dst="$1"
+       local src="$2"
+       test ! -e "$dst" -o "$src" -nt "$dst"
+}
+
+changelog_pkgname() {(
+       local cratedir="$1"
+       cd "$cratedir"
+       # dpkg-parsechangelog is really slow when dealing with hundreds of crates
+       #echo $(dpkg-parsechangelog -SSource)_$(dpkg-parsechangelog -SVersion)
+       head -n1 debian/changelog | sed -nre 's/^(\S*) \((\S*)\).*/\1_\2/gp'
+)}
+
+run_lintian() {(
+       local crate="$1"
+       local version="$2"
+       local cratedir="$crate${version:+-$version}"
+       cd "$directory"
+
+       allow_fail "$crate" $version && return 0
+
+       local base="$(changelog_pkgname "$cratedir")"
+       local out="${base}.lintian.out"
+
+       if ! ( shouldbuild "$out" "${base}_source.changes" \
+           || shouldbuild "$out" "${base}_${DEB_HOST_ARCH}.changes" ); then
+               echo >&2 "skipping already-linted ${base}_*.changes in ${out}"
+               return 0
+       fi
+
+       echo >&2 "running lintian for ${base} into ${out}"
+       rm -f "$out" "${out}.tmp"
+       changes="${base}_source.changes"
+       lintian --suppress-tags-from-file "$lintian_suppress_tags" -EIL +pedantic "$changes" | tee -a "${out}.tmp"
+       changes="${base}_${DEB_HOST_ARCH}.changes"
+       lintian --suppress-tags-from-file "$lintian_suppress_tags" -EIL +pedantic "$changes" | tee -a "${out}.tmp"
+       mv "${out}.tmp" "$out"
+)}
+
+if [ -z "$CHROOT" ]; then
+       if schroot -i -c "debcargo-unstable-${DEB_HOST_ARCH}-sbuild" >/dev/null 2>&1; then
+               CHROOT="debcargo-unstable-${DEB_HOST_ARCH}-sbuild"
+       else
+               CHROOT=${CHROOT:-unstable-"$DEB_HOST_ARCH"-sbuild}
+       fi
+fi
+GPG_KEY_ID="Debcargo Integration Test"
+run_sbuild() {(
+       local crate="$1"
+       local version="$2"
+       local cratedir="$crate${version:+-$version}"
+       cd "$directory"
+
+       allow_fail "$crate" $version && return 0
+       local base="$(changelog_pkgname "$cratedir")"
+       local dsc="${base}.dsc"
+       local build="${base}_${DEB_HOST_ARCH}.build"
+       local changes="${base}_${DEB_HOST_ARCH}.changes"
+
+       if ! shouldbuild "$changes" "$dsc"; then
+               echo >&2 "skipping already-built ${dsc} in ${changes}"
+               return 0
+       fi
+
+       if [ ! -f "signing-key.gpg" ]; then
+               mkdir -p "$PWD/gpg"
+               chmod 700 "$PWD/gpg"
+               GNUPGHOME="$PWD/gpg" gpg --batch --pinentry-mode=loopback --passphrase "" --quick-gen-key "$GPG_KEY_ID"
+               GNUPGHOME="$PWD/gpg" gpg --batch --export "$GPG_KEY_ID" > signing-key.gpg
+       fi
+
+       # Update the local repo
+       apt-ftparchive packages . > Packages
+       apt-ftparchive release . > Release
+       GNUPGHOME="$PWD/gpg" gpg --batch -a --detach-sign -u "$GPG_KEY_ID" -o Release.gpg --yes Release
+       # We use --build-dep-resolver=aspcud as both apt/aptitude fail to resolve
+       # certain complex dependency situations e.g. bytes-0.4. For our official
+       # Debian rust packages we patch those crates to have simpler dependencies;
+       # but we don't want to maintain those patches for this integration test.
+       # We also pass criteria to minimise the Rust packages we take from the
+       # Debian archive, and maximise the ones generated by this test.
+       echo >&2 "sbuild $dsc logging to $build"
+       sbuild --arch-all --arch-any --no-run-lintian --build-dep-resolver=aspcud \
+         --aspcud-criteria="-removed,-changed,-new,+count(solution,APT-Release:=/o=sbuild-build-depends-archive/),-count(solution,APT-Release:=/o=Debian/)" \
+         --extra-package ./ \
+         -c "$CHROOT" -d unstable $SBUILD_EXTRA_ARGS "$dsc"
+)}
+
+build_source() {(
+       local crate="$1"
+       local version="$2"
+       local cratedir="$crate${version:+-$version}"
+       cd "$directory"
+
+       if [ -d "$cratedir" ]; then
+               if [ -f "$cratedir/debian/changelog" ]; then
+                       local base="$(changelog_pkgname "$cratedir")"
+                       if ! shouldbuild "${base}_source.buildinfo" "$cratedir/debian/changelog"; then
+                               echo >&2 "skipping already-built ${cratedir}"
+                               return 0
+                       fi
+               fi
+               rm -rf "$cratedir"
+       fi
+
+       local deb_src_name="$($debcargo deb-src-name "$crate" "$version")"
+       local config="$config_dir/${deb_src_name}/debian/debcargo.toml"
+       if [ -f "$config" ]; then
+               option="--config $config"
+               echo >&2 "using config: $config"
+       elif [ "$deb_src_name" != "$($debcargo deb-src-name "$crate" "")" ]; then
+               config="$config_dir/old-version/debian/debcargo.toml"
+               option="--config $config"
+               echo >&2 "using config: $config"
+       fi
+
+       if ( set -x; $debcargo package $extraargs --no-overlay-write-back --directory $cratedir $option "${crate}" $version ); then
+               :
+       else
+               local x=$?
+               if allow_fail "$crate" $version; then
+                       return 0
+               fi
+               echo >&2 "crate failed: $crate $version"
+               if [ -n "$failures_file" ]; then
+                       echo "$crate" $version >> "$failures_file"
+                       return 0
+               else
+                       return $x
+               fi
+       fi
+       cd "${cratedir}"
+       mkdir -p debian/source
+       dpkg-buildpackage -d -S --no-sign
+)}
+
+cargo_tree_rec() {
+       local resolve="$1"
+       shift
+       local cache="$directory/z.${*/\//_}.$resolve.list"
+       if [ ! -f "$cache" ]; then
+               "$debcargo" build-order --resolve-type "$resolve" \
+                 --config-dir "${config_dir}" "$@" > "$cache.tmp"
+               mv "$cache.tmp" "$cache"
+       fi
+       cat "$cache"
+}
+
+run_x_or_deps() {
+       local x="$1"
+       shift
+       case "$x" in
+       *-[0-9]*)
+               spec="${x%-[0-9]*} ${x##*-}"
+               tree_args="${x%-[0-9]*}:${x##*-}"
+               ;;
+       *)
+               spec="$x"
+               tree_args="$x"
+               ;;
+       esac
+       if [ -n "$resolve" ]; then
+               set -o pipefail
+               cargo_tree_rec "$resolve" $tree_args | while read pkg ver extra; do
+                       "$@" "$pkg" "${ver#v}"
+               done
+               set +o pipefail
+       fi
+       echo $spec | while read pkg ver extras; do
+               "$@" "$pkg" "${ver#v}"
+       done
+}
+
+# make all paths absolute so things don't mess up when we switch dirs
+allow_failures=$(readlink -f "$allow_failures")
+lintian_suppress_tags=$(readlink -f "$lintian_suppress_tags")
+config_dir=$(readlink -f "$config_dir")
+directory=$(readlink -f "$directory")
+scriptdir=$(readlink -f "$scriptdir")
+
+# ensure $directory exists and maybe wipe it
+if ! $keepfiles; then
+       # don't rm the directory itself, in case it's a symlink
+       rm -rf "$directory"/*
+fi
+mkdir -p "$directory"
+
+cargo build
+debcargo="$scriptdir/../../target/debug/debcargo"
+test -x $debcargo
+
+for i in "$@"; do run_x_or_deps "$i" true; done
+for i in "$@"; do run_x_or_deps "$i" build_source; done
+# sudo schroot -c source:debcargo-unstable-amd64-sbuild -- sh -c 'echo "deb [allow-insecure=yes] file:/home/infinity0/var/lib/rust/debcargo-tmp ./" > /etc/apt/sources.list.d/local-debcargo-integration-test.list'
+if $run_sbuild; then
+       for i in "$@"; do run_x_or_deps "$i" run_sbuild; done
+fi
+if $run_lintian; then
+       for i in "$@"; do run_x_or_deps "$i" run_lintian; done
+fi
diff --git a/tests/sh/lintian-suppress-tags b/tests/sh/lintian-suppress-tags
new file mode 100644 (file)
index 0000000..003aa08
--- /dev/null
@@ -0,0 +1,88 @@
+## To be fixed by the package developer
+
+# copyright
+missing-license-paragraph-in-dep5-copyright
+space-in-std-shortname-in-dep5-copyright
+license-problem-undefined-license
+superfluous-file-pattern
+bad-exception-format-in-dep5-copyright
+
+# other source
+file-contains-fixme-placeholder
+synopsis-too-long
+description-synopsis-starts-with-article
+debian-changelog-line-too-long
+unknown-section
+spelling-error-in-binary
+rust-boilerplate
+no-manual-page
+
+## To be fixed here in debcargo
+
+out-of-date-standards-version
+package-uses-old-debhelper-compat-version
+uses-debhelper-compat-file
+upstream-metadata-file-is-missing
+
+## Cannot be fixed due to Rust crate conventions
+
+# crates don't generally have GPG signatures
+debian-watch-does-not-check-gpg-signature
+# crates don't always have a homepage
+no-homepage-field
+# crates don't always have tests
+missing-tests-control
+# crates sometimes just have long source lines
+very-long-line-length-in-source-file
+
+## Not to be fixed, due to how we package Rust in Debian and lintian being presumptuous
+
+# we install the crate into /usr/share/cargo, including most docs
+package-contains-documentation-outside-usr-share-doc
+# we install the crate into /usr/share/cargo, lintian is overzealous
+repeated-path-segment
+
+# this is a result of how we have to do rust packaging -
+# see the comment relating to Multi-Arch in the debcargo source code
+package-contains-no-arch-dependent-files
+
+# Provides issue with FTP pending resolution
+field-too-long
+
+# bug 833608
+version-substvar-for-external-package
+
+# our policy is not to file ITPs for library crates since there are so many
+initial-upload-closes-no-bugs
+
+## Not to be fixed, due to our test setup
+
+unused-override
+# lintian doesn't recognise our test "ruzt" prefix
+wrong-section-according-to-package-name
+
+# we don't finalise changelogs for this integration test
+bad-distribution-in-changes-file
+distribution-and-changes-mismatch
+
+# this is because we don't bother with excluding embedded libs in this
+# integration test. they are not allowed in Debian and would be a FTP reject
+# but we don't care for the purposes of this integration test
+
+source-is-missing
+unpack-message-for-orig
+unpack-message-for-deb-data
+unpack-message-for-source
+arch-dependent-file-in-usr-share
+arch-dependent-file-not-in-arch-specific-directory
+arch-dep-package-has-big-usr-share
+embedded-library
+font-outside-font-dir
+font-in-non-font-package
+duplicate-font-file
+source-contains-autogenerated-gperf-data
+source-contains-prebuilt-javascript-object
+windows-devel-file-in-package
+executable-not-elf-or-script
+incorrect-path-for-interpreter
+hardening-no-fortify-functions
diff --git a/tests/sh/quick-build.sh b/tests/sh/quick-build.sh
new file mode 100755 (executable)
index 0000000..749716a
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/bash
+set -e
+cargo build
+rm -rf rust-*
+target/debug/debcargo package "$@"
+nano rust-${1/_/-}-*/debian/${file:-control}
diff --git a/tests/tiny-dfr_override.toml b/tests/tiny-dfr_override.toml
new file mode 100644 (file)
index 0000000..9d8f55c
--- /dev/null
@@ -0,0 +1,16 @@
+overlay = "."
+uploaders = ["Andreas Henriksson <andreas@fatal.se>", "NoisyCoil <noisycoil@tutanota.com>"]
+
+[source]
+section = "utils"
+
+[packages.bin]
+summary = "dynamic touch bar daemon"
+description = """
+This package contains tiny-dfr, the userland touch bar daemon.
+
+tiny-dfr shows the function row and media control keys (brightness,
+volume, backlight, play, etc) on your touch bar. Currently supported
+platforms are Apple Silicon and T2 Macs.
+"""
+architecture = ["arm64", "amd64"]
\ No newline at end of file